tag:blogger.com,1999:blog-3627889459792372122024-03-13T08:53:13.092-07:00Wabi Sabi SoftwareThe Wabi Sabi aesthetic is sometimes described as one of beauty that is "imperfect, impermanent, and incomplete". This blog is about applying that aesthetic to software, cognition and philosophy.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.comBlogger62125tag:blogger.com,1999:blog-362788945979237212.post-53329497061199853822014-12-24T08:24:00.001-08:002014-12-24T08:24:20.267-08:00My writing has movedThis has been a strange year for me for writing in that most of it has gone elsewhere. I started writing a paid column for an online Amazon Web Services magazine called SearchAWS.com.<br />
<br />
If you're interested in AWS you might find these articles interesting:<br />
<br />
<a href="https://www.linkedin.com/redir/redirect?url=http%3A%2F%2Fsearchaws%2Etechtarget%2Ecom%2Ftip%2FSetting-up-your-first-AWS-account&urlhash=cAFx&trk=prof-publication-title-link">Setting Up Your First AWS Instance</a><br />
<a href="https://www.linkedin.com/redir/redirect?url=http%3A%2F%2Fsearchaws%2Etechtarget%2Ecom%2Ftip%2FAWS-CloudWatch-terms-and-definitions&urlhash=KAio&trk=prof-publication-title-link">CloudWatch Terms and Definitions</a><br />
<a href="https://www.linkedin.com/redir/redirect?url=http%3A%2F%2Fsearchaws%2Etechtarget%2Ecom%2Ftip%2FSet-up-AWS-CloudWatch-alerts-and-alarms&urlhash=WUsd&trk=prof-publication-title-link">CloudWatch Alerts and Alarms</a><br />
<a href="https://www.linkedin.com/redir/redirect?url=http%3A%2F%2Fsearchaws%2Etechtarget%2Ecom%2Ftip%2FThe-inner-workings-of-AWS-AutoScaling&urlhash=YAmK&trk=prof-publication-title-link">The Inner Workings of AWS Autoscaling</a><br />
<a href="https://www.linkedin.com/redir/redirect?url=http%3A%2F%2Fsearchaws%2Etechtarget%2Ecom%2Ftip%2FCombat-a-common-error-with-AWS-EC2-instances&urlhash=VA0C&trk=prof-publication-title-link">Combat a common error with AWS EC2 instances</a><br />
<a href="https://www.linkedin.com/redir/redirect?url=http%3A%2F%2Fsearchaws%2Etechtarget%2Ecom%2Ftip%2FSpoiler-alert-Your-AWS-application-isnt-that-mission-critical&urlhash=BrMf&trk=prof-publication-title-link">Your Mission's Not That Critical</a><br />
<a href="https://www.linkedin.com/redir/redirect?url=http%3A%2F%2Ftinyurl%2Ecom%2Fp6wdmj5&urlhash=Jlvl&trk=prof-publication-title-link">Demystifying AWS and Docker</a><br />
<br />
I've also started writing for LinkedIn Pulse News. These stories are my own observations on the software industry and on being a software developer (hopefully with the occasional insight on the wider world). If you'd like to check those out you can visit:<br />
<br />
<a href="https://www.linkedin.com/today/post/article/20140717114025-1191993-terminating-byod?trk=mp-reader-card">Terminating BYOD</a><br />
<a href="https://www.linkedin.com/today/post/article/20140820120149-1191993-escalating-to-dos?trk=mp-reader-card">Escalating TO-DOs</a><br />
<a href="https://www.linkedin.com/today/post/article/20140916122501-1191993-taking-a-collaboration-clue-from-programmers-tools?trk=mp-reader-card">Taking a collaboration clue from programmers'...</a><br />
<a href="https://www.linkedin.com/today/post/article/20141030131158-1191993-how-hard-is-the-paperwork-to-take-time-off?trk=mp-reader-card">How hard is the paperwork to take time off?</a><br />
<a href="https://www.linkedin.com/today/post/article/20141117171510-1191993-don-t-waste-my-time?trk=mp-reader-card">Don't Waste My Time</a><br />
<a href="https://www.linkedin.com/today/post/article/20141201135008-1191993--and-is-a-four-letter-word?trk=mp-reader-card">"And" is a four letter word</a><br />
<a href="https://www.linkedin.com/today/post/article/when-were-big-google-brian-tarbox?trk=mp-reader-card">When we're as big as Google...</a><br />
<a href="https://www.linkedin.com/today/post/article/moral-story-isnt-balance-brian-tarbox?trk=mp-reader-card">The Moral of the story isn’t balance…</a><br />
<a href="https://www.linkedin.com/today/post/article/facebook-quizes-advertising-brian-tarbox?trk=mp-reader-card">Facebook quizes as advertising</a><br />
<br />
As always I'd love to hear comments from you, either here or on those pages. If you have topics you'd like covered please let me know that as well.<br />
<br />
Thanks.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-62171843472618989022014-05-29T05:52:00.000-07:002014-05-29T05:52:38.636-07:00I am now writing for SearchAWS.com a web magazine for the Amazon Web Services spaceI've started a new writing venture, writing "tips" for a new web magazine devoted to the Amazon Web Services space. These tips are short (600 word) explanations of how to do various AWS tasks or how to understand aspects of Amazon's offerings.<br />
<br />
Many of the tips seem to be evolving into two part series: an overview and background tip followed by a cookbook style tip. I've taken this approach because I find that many aspects of AWS only make sense if you understand the perspective they are coming from. They also have a fair amount of non-standard terminology that can be a road block until the terms are explained.<br />
<br />
So far I've written on AWS registration, creating your first instance, and understanding CloudWatch. Please check out searchaws.com and let me know if you have suggestions for topics. Thanks.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com1tag:blogger.com,1999:blog-362788945979237212.post-52285975657676925672013-11-18T10:34:00.001-08:002013-11-18T10:41:45.848-08:00Random observations from Amazon's re:Invent conferenceI just returned from Amazon's re:Invent developers conference and had a few social observations.<br />
<br />
a) the gender breakdown seemed to be about 99% male which is depressing<br />
<br />
b) every presentation I saw was given on a MacBook<br />
<br />
c) in the audiences I saw people taking notes on iPads and all manner of 7 inch tables (its hard to distinguish iPad Mini from Kindle Fire from generic Android at a distance.<br />
<br />
d) I <i>think</i> I saw a couple of PC laptops during the week and I saw zero Surface tablets.<br />
<br />
e) I did for the first time see two people wearing Google Glasses and I heard the term Glass-hole!<br />
<br />
f) The Venetian hotel has a truly amazing recreation of Saint Marks Square…they basically built a IMAX like curved ceiling over the entire indoor plaza creating a realistic impression of being outdoors.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzoM3w4gMekAS4D0-z8uz9hD0IMM5LjLMMkGBnIkyOC4ra1A4_tSUaJHB7ueor0kZ9ExJMENAKyKFqPz3gkeVFU-ZGLQqDilGUxrXUJ1mSLJnk5NKcCmc1uqJHt1trZoyOmS2Ux1FtaU/s1600/photo-7.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzoM3w4gMekAS4D0-z8uz9hD0IMM5LjLMMkGBnIkyOC4ra1A4_tSUaJHB7ueor0kZ9ExJMENAKyKFqPz3gkeVFU-ZGLQqDilGUxrXUJ1mSLJnk5NKcCmc1uqJHt1trZoyOmS2Ux1FtaU/s400/photo-7.JPG" width="400" /></a></div>
<br />
g) the technology part of the conference (the real point after all) was of course very cool and compelling but thats a post for another day!Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-37221154432664124132013-10-02T10:14:00.001-07:002013-10-02T10:14:44.535-07:00New article at PragPub<br />
I have another article published at PragPub. That used to be a free publication but they've had to start charging (a very small and reasonable fee) for the magazine. You can get to the paid magazine at <a href="http://www.swaine.com/pragpub">www.swaine.com/pragpub</a>.<br />
<div>
<br /></div>
<div>
They are taking a very open approach and allowing authors such as myself to provide free links to our articles. So, here is a link to a copy of that article: <a href="https://www.dropbox.com/s/4qwy26krq4cykuv/AppsVsWebFinal.pdf">hAppsVsWebFinal.pdf</a></div>
<div>
<br /></div>
<div>
As always, comments are welcome.</div>
Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-75046095449160110812013-09-12T08:22:00.001-07:002013-09-13T12:09:20.962-07:00How to Setup Amazon CloudWatch to Send Alarm Emails<!--[if !mso]>
<style>
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<![endif]--><!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<br />
<div class="MsoNormal" style="margin-bottom: 3.0pt; margin-left: 0in; margin-right: 0in; margin-top: 12.0pt; mso-outline-level: 1; mso-pagination: none;">
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<br />
<div class="MsoNormal">
Amazon Web Services are very powerful and some things are harder than you might expect. Getting an email notification that something is wrong is one of those things. I originally wrote this up so that I would remember next time I needed it and then decided it might be helpful to others.<br />
<br />
You need to set up several things to get this to work. You need a metric, which is some value
that indicates if the system is ok or not. You need an alarm that fires when that metric indicates
failure. You need an SNS topic to
get notified when an alarm fires.
And lastly you need a subscription to that topic which a where you
specify a phone number or email to receive the alarm notification.<o:p></o:p></div>
<div class="MsoNormal">
<span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;"><br /></span></div>
<div class="MsoNormal">
</div>
<span style="line-height: 115%;"><span style="font-family: Times, Times New Roman, serif;">create an SNS topic from SNS gui (press “Create and
Add”)</span></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2Zer4MZrTFmlQZLhyddL1PlNfs5x1YvbZ0oY0IQ-og6bVJ-CzE1g6QOZ6BnksFW2QQqDei3YTwvOSYUKAjEKoCsC0c5wgW7WvYFhbe-THkfbysuLEhPmtIH-mS67WTgiIG13cpdNQBbI/s1600/createAndAdd.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2Zer4MZrTFmlQZLhyddL1PlNfs5x1YvbZ0oY0IQ-og6bVJ-CzE1g6QOZ6BnksFW2QQqDei3YTwvOSYUKAjEKoCsC0c5wgW7WvYFhbe-THkfbysuLEhPmtIH-mS67WTgiIG13cpdNQBbI/s1600/createAndAdd.jpg" /></a></div>
<span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;">
<!--[if !supportLineBreakNewLine]--><br />
<!--[endif]--></span><!--EndFragment--><br />
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;">give the topic a name and a display name</span><!--EndFragment-->
<br />
<span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVndFi46TFmBxcQVZMrSN6RGJzk0HFqDBQrWUHXvtIFd57r2UU1AbddiJmbE140SSoovHC0qkJFxV7H-nYwGy2y7MOA_f7QSC1ob2tKXdipvXaz-7tBBObWcxddNspRzuDjysw2a7fsW4/s1600/topicName.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVndFi46TFmBxcQVZMrSN6RGJzk0HFqDBQrWUHXvtIFd57r2UU1AbddiJmbE140SSoovHC0qkJFxV7H-nYwGy2y7MOA_f7QSC1ob2tKXdipvXaz-7tBBObWcxddNspRzuDjysw2a7fsW4/s400/topicName.jpg" width="400" /></a></div>
<span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;"><br /></span>
<span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 1in; text-indent: -0.25in;">
<span style="font-family: Times, 'Times New Roman', serif; font-size: 12pt; text-indent: -0.25in;"><span style="font-size: 7pt;"><br /></span></span>
<span style="font-family: Times, 'Times New Roman', serif; font-size: 12pt; text-indent: -0.25in;"><span style="font-size: 7pt;"><br /></span></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 1in; text-indent: -0.25in;">
<span style="font-family: Times, 'Times New Roman', serif; font-size: 12pt; text-indent: -0.25in;"><span style="font-size: 7pt;"> </span></span><span style="font-family: Times, 'Times New Roman', serif; font-size: 12pt; text-indent: -0.25in;">create a subscription…some place to send the
notification</span></div>
<span style="font-size: 12pt; line-height: 115%;"><span style="font-family: Times, Times New Roman, serif;">HTTP, HTTPS, email, sms, SQS
and protocol specific “endpoint”</span></span><!--EndFragment-->
<br />
<div class="MsoNormal">
<span style="font-size: 12pt; line-height: 115%;"><span style="font-family: Times, Times New Roman, serif;"><br /></span></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn7RsU_NXcqLOCgDY5S566aVxs9UwJmFKAie9ItsX0_-y5yDT0EGVAsFdMs-EIArls3atul1FdW6u8EAhT_IxvimMUGWyn9Ho-8e30euIZLYSkUEOHtYY9daN8iYWt3D0EZSz0TbNY_eQ/s1600/createSubscription.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn7RsU_NXcqLOCgDY5S566aVxs9UwJmFKAie9ItsX0_-y5yDT0EGVAsFdMs-EIArls3atul1FdW6u8EAhT_IxvimMUGWyn9Ho-8e30euIZLYSkUEOHtYY9daN8iYWt3D0EZSz0TbNY_eQ/s400/createSubscription.jpg" width="400" /></a></div>
<span style="font-size: 12pt; line-height: 115%;"><span style="font-family: Times, Times New Roman, serif;"><br /></span></span>
<span style="font-size: 12pt; line-height: 115%;"><span style="font-family: Times, Times New Roman, serif;"><br /></span></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
</div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 1.5in; text-indent: -1.5in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">You will receive a confirmation email, text, etc. depending on the protocol you
specified asking if you really want to create this subscription.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 1.5in; text-indent: -1.5in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"><br /></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 1.5in; text-indent: -1.5in;">
<a href="http://www.blogger.com/blogger.g?blogID=362788945979237212" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="http://www.blogger.com/blogger.g?blogID=362788945979237212" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="http://www.blogger.com/blogger.g?blogID=362788945979237212" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="http://www.blogger.com/blogger.g?blogID=362788945979237212" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="http://www.blogger.com/blogger.g?blogID=362788945979237212" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;">Take note of the “ARN” for the topic, it will be
used as the alarm-action below</span><!--EndFragment-->
</div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 1.5in; text-indent: -1.5in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"><br /></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 1.5in; text-indent: -1.5in;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5Ckk58zGybW27X-N9ORS_mwidWyMVTtniln-oTAqM2iRpVgGJZiu8_aGr3JMnkRoTuQI8yDyQ5f0SSGQwIJB4vYVH1vsmpqDT9Tr8C0jaXcucYvQpQuyDiVDtmqTFtd12wd-8KFXQ94k/s1600/arn.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="117" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5Ckk58zGybW27X-N9ORS_mwidWyMVTtniln-oTAqM2iRpVgGJZiu8_aGr3JMnkRoTuQI8yDyQ5f0SSGQwIJB4vYVH1vsmpqDT9Tr8C0jaXcucYvQpQuyDiVDtmqTFtd12wd-8KFXQ94k/s400/arn.jpg" width="400" /></a></div>
<br />
<br />
<br /></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
</div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<br /></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
</div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">Create a Cloud Watch metric named
ZkServerCount<o:p></o:p></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">"mon<a href="http://www.blogger.com/blogger.g?blogID=362788945979237212" name="_GoBack"></a>-put-data" is used both to put the data and to create the metric itself if it doesn’t
already exist.<o:p></o:p></span><br />
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"><br /></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">We use the command line to create
the metric because CloudWatch seems to have a problem if you have defined a lot
of metrics…and its easy to create a lot of metrics. Each instance you create automatically gets half a dozen
standard metrics and those metrics live for 14 days regardless of how long your
instance lives. If you create thousands
of worker instances you seem to
overwhelm the CloudWatch gui.
We’ve reported this as a bug and are working with Amazon about it but in
the meantime we use the command line to create metrics.<o:p></o:p></span><br />
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"><br /></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">Setting up to use the command
line<o:p></o:p></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 63pt;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">download
the jars from </span><a href="http://aws.amazon.com/developertools/2534">http://aws.amazon.com/developertools/2534</a><span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"><o:p></o:p></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 63pt;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">setup
environment vars as described in README.TXT. You must in particular setup the AWS_CLOUDWATCH_HOME
variable<o:p></o:p></span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 63pt;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">set up
credentials as per the readme.<o:p></o:p></span><br />
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"><br /></span></div>
<span style="font-family: Helvetica; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-fareast;">Run this command which will both create the metric and give it its first
value of three: <i>mon-put-data –metric-name
ZkServerCount –namespace MyNameSpace –timestamp 2013-08-25T00:00:00Z – value 3</i><br />
<!--[if !supportLineBreakNewLine]--><br />
<!--[endif]--></span><!--EndFragment--><br />
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<br />
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">Create a Cloud Watch metric alarm
based on that metric; t</span><span style="font-family: Helvetica; font-size: 12pt;">his alarm will fire when the
metric’s value is less than 3:</span></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<span style="font-family: Helvetica; font-size: 12pt;"><br /></span></div>
<i><span style="font-family: Times, Times New Roman, serif;"><span style="line-height: 115%;"><code>bin/mon-put-metric-alarm –alarm-name zk-mon
–alarm-description “Alarm upon zookeeper server failure” –metric-name
ZkServerCount –namespace MyNameSpace –statistic Average –period 300 –threshold
3 –comparison-operator LessThanThreshold –evaluation-periods 1 –alarm-actions </code>arn:aws:sns:us-east-1:abc123:ZooKeeper_failure<</span></span></i><span style="line-height: 115%;"><span style="font-family: Times, Times New Roman, serif;"> </span></span></div>
<br />
<span style="line-height: 115%;"><span style="font-family: Times, Times New Roman, serif;"><br /></span></span>
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<br />
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<span style="font-family: Helvetica; font-size: 12.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">Create some code that will
periodically run the mon-put-data command from step 2 above.</span><span style="font-family: Helvetica; font-size: 12pt; line-height: 115%;"> This looks like a lot of code to put a single value into the system but
bear in mind that this includes some one-time setup, and that you can add multiple
values at a time.</span> </div>
<span style="line-height: 115%;">
<!--[if !supportLineBreakNewLine]--><br />
<!--[endif]--></span><!--EndFragment--><br />
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<br /></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.25in;">
<code></code></div>
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<br />
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.5in;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">public void putMetric() {<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.5in;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">
BasicAWSCredentials
credentials =
BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.5in;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"> </span></i><i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">AmazonCloudWatchClient acwc
= new AmazonCloudWatchClient(credentials);<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin: 0in 0in 0.0001pt 0.5in;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"> Double metricValue = 3.0;</span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"> MetricDatum datum2
= new MetricDatum().<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">
withMetricName(INSTANCE_COUNT_METRIC_NAME).<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">
withTimestamp(new
Date()).<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">
withValue(metricValue). <o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">
withUnit(StandardUnit.Count);<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"> PutMetricDataRequest putMetricDataRequest = new PutMetricDataRequest().<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">
withNamespace(FRAGMENT_NAMESPACE).<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;">
withMetricData(datum1, datum2, datum3);<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-size: 12.0pt; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Times New Roman"; mso-fareast-theme-font: minor-fareast;"> acwc.putMetricData(putMetricDataRequest);<br />
}<o:p></o:p></span></i></div>
<!--EndFragment--><br />
<!--EndFragment--><br />
<!--EndFragment-->When you are all done its of course a good idea to trigger the condition manually just to make sure you actually do get that text or email that you really don't want to get for real!<br />
<!--EndFragment--><br />
<!--EndFragment-->Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com8tag:blogger.com,1999:blog-362788945979237212.post-67913022241275331112013-04-06T13:31:00.001-07:002013-04-06T13:58:39.762-07:00Moving to Agile: estimates and promises<span style="background-color: black; color: white; font-family: inherit;"><br /></span>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;">In transitioning a legacy team to agile the issue of estimates vs promises and how engineers and management interprets them is acknowledged as key. Management often asks engineers for estimates and then treats the answers as promises. This leads to a whole set of problems which are documented in the agile literature. I often think that communications difficulties can be helped by reversing a situation so lets try that here.</span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;"><br /></span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;">I wonder if we can help clarify the difference between estimates and promises by asking management for an estimate. “<i>If my team gives you product X by date Y will you give us a specific level bonus?</i>”. Any management I’ve seen will say they can’t promise a specific bonus in the future because there are too many free variables.</span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;"><br /></span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;">To which we say “exactly”.</span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;"><br /></span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;">If instead we say “we believe we have an 80% chance of hitting date Y with feature set Z” might we get them to say “there’s a 75% chance of getting a bonus of D dollars”? As we got closer and closer to the target release date might we get them to reduce the uncertainly of our bonus level as we reduce the uncertainly of the feature set?</span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;"><br /></span></div>
<div style="line-height: 1.3em;">
<span style="background-color: black; color: white; font-family: inherit;">I don’t think most management would actually do this but it might help them see our estimates in a new light.</span></div>
Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com1tag:blogger.com,1999:blog-362788945979237212.post-17055792593422022352013-03-26T10:20:00.001-07:002013-03-26T10:20:31.682-07:00Is It Coding in Scala or Coding With Courage And Humility That Matters?
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Zoom>0</w:Zoom>
<w:TrackMoves>false</w:TrackMoves>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>18 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>18 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>0</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:DontGrowAutofit/>
<w:DontAutofitConstrainedTables/>
<w:DontVertAlignInTxbx/>
</w:Compatibility>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="276">
</w:LatentStyles>
</xml><![endif]-->
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"Times New Roman";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"Times New Roman";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<br />
<div class="MsoNormal">
Scala is all the rage these days, replacing its legacy
cousin Java in the hearts and minds of all the cool kids. Admitting that you still code in Java
is the geek’s equivalent to saying you drive a mini-van and don’t have a
twitter handle. We’ve all heard
the proclamations of how much more powerful and succinct Scala is..and I’ll
admit to having done some of that myself.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
While not dismissing those statements, because I do in fact find Scala to be a
better language, I think there is
another cluster of factors at work here as well. Those factors are courage and humility.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
There is a correlation between Java and large, often
distributed teams. This may
be largely in part due to the relative age of the language. It is established and “mature” to use a
kind word. If you have a 50-100
person development shop with offices in the US as well as in some subset of China,
India, Russia you are very likely
to be a Java shop. If you have
maintenance or sustaining teams as well as a development team you are likely to
be a Java shop. If you spend a
fair bit of your time on “process” you are likely to be a Java shop.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Notice that I said “likely”. There are lots of counter examples. My own company uses Java and we have
only three programmers. None the
less, I think the preceeding statements are <i>generally</i>
true.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
So what? Well,
my assertion is that along with large, process oriented and distributed comes
the notion of lowest common denomenator coding. As the size and geographic distribution of your team grows
so does concern about “<i>those other
programmers</i>” being able to understand and maintain your code. That leads us to want to standardize
and simplify the code. We want to
make the code clear to that possibly junior coder who may be new to the
project, who may never have absorbed the designs, and who many not be familiar
with the code base.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
This leads us to write code like:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<i>public int
calculateTheValue(long someInput, long someOtherInput) {<br />
long intermediateOne
= someInput * getSomethingElse();<br />
intermediateOne +=
someOtherInput;<br />
intermediateOne =
someMethod();<br />
….<br />
return intermediateOne;<br />
}<o:p></o:p></i></div>
<div class="MsoNormal">
<i><br /></i></div>
<div class="MsoNormal">
There is nothing wrong with this code and to a newbie its
certainly more accessible than:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<i>public int calculateTheValue(long
someInput, long someOtherInput) {<br />
return
somethingElse(someInput, someMethod(someOtherInput));<br />
}<o:p></o:p></i></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The problem is that 10 lines of code versus 3 for every
method in your system results in a sea of code where you literally can’t see
the forest for the trees. I can
tell what each individual<a href="" name="_GoBack"></a> line of code does but I have no
idea <i>why</i> because I can never see more
than 0.01% of the code on my screen at a time.</div>
<div class="MsoNormal">
Some readers might protest at this point that this is all
just formatting and Eclipse or Emacs could in principal convert between these
two representations. To which I
say: not so much.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The functional approach is all about the composition of a
method from a collection of existing functions. In this approach it is clear that the new method is “just”
using the existing methods. The
new method has no logic per se other than using the output of other…presumably
well named and tested functions.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the more familiar Java approach each method is a new
creation created out of whole cloth.
It might do any old thing it wants. In this case freedom and creativity are to be
considered bad things. Each method
must be examined line by line to see what it might be doing. Lets look at a bit of open source code
I’m actually currently debugging:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: .5in;">
<i>int
to = readTimeout - clientCnxnSocket.getIdleRecv();<br />
int timeToNextPing = (readTimeout / 2)
- clientCnxnSocket.getIdleSend();
<br />
if (timeToNextPing <= 0) {<br />
sendPing();<br />
clientCnxnSocket.updateLastSend();<br />
} else {<br />
if
(timeToNextPing < to) <br />
to = timeToNextPing;<br />
}<br />
clientCnxnSocket .doTransport(to);<o:p></o:p></i></div>
<div class="MsoNormal" style="margin-left: .5in;">
<i><br /></i></div>
<div class="MsoNormal">
After some period of study we can see that this code has two
variables related to time outs: “to” and “readTimeOut”. Based on the results of two “getIdle”
calls we might send a ping, and then we mutate “to” in a couple of possible
ways and then use it as a parameter to a socket call. Further investigation reveals that “to” is the length of
time the socket method may spend in a blocking “select” call. Thus, “to” is related to how long we
can block before sending another ping.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I’ve spent the last couple of hours trying to track down a
bug in this system and the problem is that every single line is ontologically
at the same level. By that I mean
that any of them could have or be a side effect, any could do something other
than whats expected and the gestalt of what this code fragment intends can only
be gleaned by close study.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I’ll assert that the following code does not suffer from
those flaws:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: .5in;">
<i>if(timeToPing())
sendPing();<br />
clientCnxnSocket(safeTimeToWaitForRead());<o:p></o:p></i></div>
<div class="MsoNormal" style="margin-left: .5in;">
<i><br /></i></div>
<div class="MsoNormal">
And that brings us to the humility side of the
equation. Its ok to write little
one line functions that just do the one thing that their name implies. TimeToPing is not a function you will
put on your resume. You will not
proudly show it to your coworkers.
You will not tell your husband/wife/partner about the amazing bit of
code you wrote today. This one
line function will sit there quietly, unnoticed…working.</div>
<div class="MsoNormal">
If we have the humility to write simple functions and then
have the courage to combine them into composite functions without extraneous
scafolding and temporary mutable variables then we have a chance to achieve
greatness…even in a legacy language.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To be sure, there are things that are trivial in Scala that
simply can not be done in Java. I
know of no way to annotate a method to indicate that it does or doesn’t ever
return null. We recently
changed such a method to never return null. There is no way however to find all the code that’s now unncessary. Or assuming we had made the opposite
change…to find the code that was not an NPE timebomb. <a href="http://www.blogger.com/blogger.g?blogID=362788945979237212#_ftn1" name="_ftnref" title=""><span class="MsoFootnoteReference"><!--[if !supportFootnotes]-->[1]<!--[endif]--></span></a> </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In Scala of course if your
function might return a Foo but might return nothing you return an
Option(Foo)…and function’s callers <b>must</b> deal with the Option(Foo) or they will
not compile. This isn’t fixed in
Java 7, nor will it be fixed inJava’s 8, 9 or 10. Null is just baked into the language.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Java isn’t going to be “replaced” by any of the newer
languages. It will continue to
lose market share but will command a large segment of the market for the
foreseeable future. Its also clear
that Java will continue to evolve and will over time gain missing features such
as lamda expressions and better package structure. Other things like null and the Generics system are likely to
be with us to the bitter end. For good or bad erasures and
generics are part of the language now and forever. Java 8 sprinkles a bit of syntactic sugar allowing the
second repeat of the type to be omitted as in:</div>
<div class="MsoNormal" style="text-indent: .5in;">
<i>HashMap<string integer=""> myHashMap = new HashMap<>();<o:p></o:p></string></i></div>
<div class="MsoNormal">
but that’s a fairly trivial improvement in this age of
modern type inference languages.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
What this means is that engineers working with Java need to
do the best they can with a 15 year old language. Courage and Humility can help with that. </div>
<div class="MsoNormal">
<br /></div>
<div>
<!--[if !supportFootnotes]--><br clear="all" />
<hr align="left" size="1" width="33%" />
<!--[endif]-->
<div id="ftn">
<div class="MsoFootnoteText">
<a href="http://www.blogger.com/blogger.g?blogID=362788945979237212#_ftnref" name="_ftn1" title=""><span class="MsoFootnoteReference"><!--[if !supportFootnotes]-->[1]<!--[endif]--></span></a> Yes, we
could use PMD but that just points out that there is no support for such things
in the language itself.</div>
</div>
</div>
<!--EndFragment-->Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com4tag:blogger.com,1999:blog-362788945979237212.post-64233266610770910582013-01-23T11:24:00.002-08:002013-01-23T11:24:40.890-08:00Nothing but better hiring will fix thingsRecently in Slashdot there have been a series of posts about the quality level of the software at various companies. They've had titles like "How can I make my team write better code?" or "How can we improve our code quality?" <br />
<br />
I also subscribe to numerous blogs and MeetUps and User Groups where titles like "Do 'x' to improve" are fairly standard.<br />
<br />
I might just be getting my jaded but I'm coming to the conclusion that there is one and only one thing that can improve the quality of the software you/your team produces. That one thing is better hiring. To quote Joel On Software..the only two answers after an interview are "Hell yes!" or "No".<br />
<br />
By and large people either care passionately about the code the write ... or they don't. In over thirty years of doing this I can't recall a case where a "bad" coder read a book, went to a class, attended a conference or had a talk with management and suddenly started caring.<br />
<br />
That's a bit depressing because I speak at conference and have published lots of papers! On the other hand, my papers and talks have been aimed at the subset of our field that already care and are just looking to hone their skills. Trying to convince someone that unit testing, proper naming, or coherent design was a good thing is just a waste of time. People either "got it" a long time ago or they're not going to get it. Sorry.<br />
<br />
So, work to get your team to hire better people or go someplace that already does. I just don't see another option.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-88779635416436720942012-12-05T07:18:00.002-08:002012-12-05T07:18:32.974-08:00New Article in Pragmatic ProgrammerJust a quick note to say that I had another article published at the Pragmatic Programmer's:<br />
<a href="http://pragprog.com/magazines/2012-12/agile-in-the-small">http://pragprog.com/magazines/2012-12/agile-in-the-small</a>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com3tag:blogger.com,1999:blog-362788945979237212.post-14167896178061884072012-10-24T07:24:00.000-07:002012-10-24T07:24:02.480-07:00Picking the next toys just got harderMy VerizonWireless contract is up in three weeks, my Kindle just died and Apple just introduced the iPad Mini so I've got some deciding to do!<br />
<br />
I current travel with my 13" MacBook Air, a 2 year old Android phone and often my iPad2 as well. The MacBook Air is my primary laptop and serves as my coding and general content creation platform. The Android phone is going into the crusher as soon as possible, to be replaced with an iPhone. Apple isn't perfect but they support their devices for longer than 20 minutes so it "never again" for Android.<br />
<br />
So now we've dealt with phone calls, navigation, quick email checks, quick web browsing, coding and content creation. What's left?<br />
<br />
The iPad has been getting pretty lonely since I got the Air. They're both big enough to need a carry bag so if I have the iPad I almost certainly have the Air as well. This leaves time on the train commuting to work as about the only time I'd use the iPad because there's really not room in our crowded train for the Air. So I use the iPad for games and some reading.<br />
<br />
Do I really need either a Kindle or an iPad Mini? (And when I say "need" I mean it in the geeky sense as in can I develop a rational for it).<br />
<br />
The only thing I can think of using an iPad Mini for rather than my existing iPad is reading; lets face it the iPad gets heavy after a while. But I could get a Kindle Paper White for about a third the cost or a base Kindle for less than a quarter of the cost of the Mini. I'd rather get the Paper White but they're back ordered for 4-6 weeks so that's not an option.<br />
<br />
Put another way: I can get an iPhone and a base Kindle for less than the cost of the Mini.<br />
<br />
So, for folks who don't already own an iPad the iPad Mini might be a great idea but I don't see many people getting both.<br />
<br />Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-7875243752906748192012-07-28T06:29:00.000-07:002012-07-28T06:29:32.627-07:00Finding your voiceIn the past six weeks I've attended a week long Writer's Conference at Wesleyan University, a week long Native American and World Flute Conference at University of Wisconsin and changed jobs (going from a 40,000 person company to a 6 person startup).<br />
<br />
I like to look for common threads and the thread here is finding one's voice.<br />
<br />
Voice is sometimes thought of as the same thing as "style" which may help explain the idea of programmers having a voice but I think it goes far beyond that.<br />
<br />
At the writer's conference we did close readings ("inspections") of various works, looking for themes and patterns and voice. Voice here meant a way of saying things that was engaging, illuminating, understandable and among other things predictable. We talked about various contracts a writer can implicitly establish with a reader such as mentioning a shotgun in a foreshadowing paragraph implies a later use of that gun in some future scene.<br />
<br />
At the flute festival we attended Master Classes on topics such as use of various scales (major, minor, mixolydian), how to add embellishments or ornaments to ones playing and how to tell a story by use of tempo and volume and such. While the standard orchestral flute has about 20 keys the various native flutes have six or four keys...and the didgeridoo has no keys. This can be seen as limited but a smaller set of notes to choose from just means one has to use other ways to produce a full and interesting story. Thus voice.<br />
<br />
In my new job I am the second programmer on a medium sized system...meaning that the system was entirely written by a single person. It definitely has style because the person who wrote it has strong feelings about the myriad of design choices he's made along the way. He's also free about the choices that were made without a strong sense of one choice being clearly better than another.<br />
<br />
His voice is of course different from mine. We have very different backgrounds and life experiences, but the point is that I can see his voice in the code and I quite like it. I'm sure that over time our two voices will influence each other, but I suspect that they will remain distinct.<br />
<br />
In the past I've been a strong advocate of static analysis tools such as CheckStyle. I don't think I'll be lobbying so much for that tool here. I'm beginning to think that such tools are most applicable for shops where the engineers have not yet found their voice.<br />
<br />Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com1tag:blogger.com,1999:blog-362788945979237212.post-60994577466589087752012-06-22T11:46:00.000-07:002012-06-22T12:03:02.626-07:00Thoughts about e-Books after attending a Writer's ConferenceI just returned from attending the 2012 Wesleyan Writer's Conference in Middletown, Conn. It was a week jam packed with close reading of poetry, thematic explorations of fiction, exploration of dialog in non-fiction and of course speculation on the future of books, e-books and publishing.<br />
<br />
A couple of ideas came to me during the week that I'd like to share. Let me preface by saying that for me reading <i>means</i> reading books or PDFs on my Kindle or via a Kindle Reading app on my my iPad, MacBook Air or HP laptop. Last year I read 42 books and only two of them were of the dead tree variety.<br />
<br />
One of the great features of Kindle reading (and presumably also for Nook reading though I can't say from experience) is the ability to trivial get the dictionary definition of works in the text via a single click. I like to pride myself on an extensive vocabulary but there are lots of words that I "mostly know what they mean but could not give you a coherent definition". I make it a point to click on these words and get a real definition. That's all well and good but we should be able to do better.<br />
<br />
Many books with extensive sets of characters contain a <span class="Apple-style-span" style="font-style: italic; line-height: 19px;"><a class="mw-redirect" href="http://en.wikipedia.org/wiki/Dramatis_personae" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; color: #0645ad; text-decoration: none;" title="Dramatis personae"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">Dramatis personae</span></a><span class="Apple-style-span" style="font-family: sans-serif; font-size: 13px;"> </span></span><span class="Apple-style-span" style="line-height: 19px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">or list of characters at the beginning of the book. This can be especially important when reading Science Fiction where some authors show how alien their characters are by giving them unpronounceable names. Imagine being able to click on a name in your book and get the quick description of who that person is?</span></span><br />
<span class="Apple-style-span" style="line-height: 19px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br /></span></span><br />
<span class="Apple-style-span" style="line-height: 19px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">A further enhancement to this idea would be to generate what we know about the person at that point in the story.</span></span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><span class="Apple-style-span" style="line-height: 19px;"><br /></span></span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><span class="Apple-style-span" style="line-height: 19px;">Some people might view these not as enhancements but as crutches that remove the need to immerse oneself in the book. I would respectively disagree and say they provide a way to become more immersed in the book, but it doesn't matter. They are mostly just examples of simple things we can do to play with the book reading experience.</span></span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><span class="Apple-style-span" style="line-height: 19px;"><br /></span></span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><span class="Apple-style-span" style="line-height: 19px;">Sadly, while Amazon provides an API to create applications like games on the Kindle they do not (as far as I've been able to tell), provide a way to modify/extend the actual book reading experience. I don't blame them as most "enhancements" would like be misguided but its still a shame that we can't currently play with the idea.</span></span>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com3tag:blogger.com,1999:blog-362788945979237212.post-84067531378552673282012-05-03T08:07:00.001-07:002012-05-03T08:07:35.534-07:00Scala Static AnalysisI am finally getting around to working on my next pet project which is a Static Analysis tool for Scala.<br />
<br />
Java has a number of quite good Static Analysis tools such as:<br />
checkstyle - enforces a large set of user configurable rules about things like<br />
max-line-length, max-parameters, max-if-nesting, <br />
max Cyclomatic complexity, etc<br />
findbugs - looks for common bug patterns<br />
<br />
Scala, for all of its power currently lacks such tools. There is even debate within the community if such tools matter for functional languages. Still, it seems like a very interesting problem to me so I decided to give it a go.<br />
<br />
In talking with people at Boston Scala Days 2012 the consensus was that a compiler plugin was the best way to approach this problem. So, I started thinking about a two pronged approach:<br />
<br />
1 - develop a compiler plugin to get access to the Abstract Syntax Tree of a program<br />
<br />
2 - start a discussion about what kind of rules or metrics might make sense for a language like Scala.<br />
<br />
The plug-in itself splits into at least two parts: the skeleton that hooks itself into the compilation process and the part that accesses the AST itself.<br />
<br />
There is a great "how to" article on the compiler plug-in skeleton at <a href="http://www.scala-lang.org/node/140">http://www.scala-lang.org/node/140</a> This article shows how to build a trivial plug-in that looks for divide by zero errors. The guts are in the "apply" method...and that's where things got spooky for me!<br />
<br />
def apply(unit: CompilationUnit) {<br /> for ( tree @ Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0)))) <- unit.body;<br /> if rcvr.tpe <:< definitions.IntClass.tpe) <br /> {<br /> unit.error(tree.pos, "definitely division by zero")<br /> }<br /> }<br />
I know that this method iterates over the unit.body tree looking for items that are division, with a literal zero and an integer. That doesn't mean however that I fully grok the Tree hierarchy and its various flavors of Apply and Select methods!<br />
<br />
I will say I'm getting some very good help on this via a question I asked on StackOverflow:<br />
<a href="http://stackoverflow.com/questions/10419101/how-can-i-find-the-statements-in-a-scala-program-from-within-a-compiler-plugin">http://stackoverflow.com/questions/10419101/how-can-i-find-the-statements-in-a-scala-program-from-within-a-compiler-plugin</a><br />
<br />
More as I get smarter about Abstract Syntax Trees! If anyone wants to help on this project please contact me as I clearly could use help. I'll put the project up on GitHub soon.<br />Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com2tag:blogger.com,1999:blog-362788945979237212.post-58940520654230615482012-04-30T16:27:00.000-07:002012-04-30T16:27:18.949-07:00Hard because its hard or because its easy?Some problems are hard because they're actually hard.<br />
Some problems however are only hard because the answer is so easy that no one tells you about them.<br />
<br />
I recently encountered a problem of the latter type while playing around with Scala's Option type. If you are not familiar with it Option is a type that can either hold a thing or hold nothing. So, Option[String] is either a String or its nothing (actually None in Scala). For reasons that you probably either already know about or don't care to know this is very useful when coding in Scala.<br />
<br />
You can say things like:<br />
foo match {<br />
case None => // handle the case where is is None<br />
case Some => // handle the case where there is something<br />
}<br />
<br />
(Of course we Scala folks like tricky things and so we'd tend to say<br />
"case _ =>" in the second case, but for now you can ignore that as showing off).<br />
<br />
So, imagine you are in the second case and actually have a <b>Some</b>thing. How do you get at it?<br />
<br />
You might think you'd say foo.Some, or Some(foo) or a variation on that theme. Failing that you might check the documentation on Option or read up on the topic in one of the several fine books on the topic. Unless you looked someplace I didn't you won't find too much. Foo.some doesn't exist and most variations of Some(foo) give truely unexpected answers. For example, try this:<br />
<br />
val bla = 4<br />
val foo : Option[Long] = Some(3L)<br />
println(bla > foo)<br />
<br />
This results in the pretty confusing error message:<br />
<br />
<console>:10: error: overloaded method value > with alternatives:</console><br />
(x: Double)Boolean <and></and><br />
(x: Float)Boolean <and></and><br />
(x: Long)Boolean <and></and><br />
(x: Int)Boolean <and></and><br />
(x: Char)Boolean <and></and><br />
(x: Short)Boolean <and></and><br />
(x: Byte)Boolean<br />
cannot be applied to (Some[Option[Long]])<br />
bla > Some(foo)<br />
^<br />
<br />
So, how do you access the "some" part of an Option? The "obvious after the fact" answer is with "get".<br />
<br />
You can say println(bla > foo.get)<br />
<br />
I bet that most people learning Scala have struggled with this or perhaps are still struggling with it. However, it seems like such a dead simple case that most people won't admit to having been confused by it.<br />
<br />
That's my definition of hard because its "too simple to mention".<br />
<br />
<br />
<br />Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com3tag:blogger.com,1999:blog-362788945979237212.post-39474716145943752162012-04-18T09:35:00.002-07:002012-04-18T09:35:38.174-07:00Retrospective Velocity - part 3 of 3<span style="font-family: Calibri;">While it may take a huge effort to get your organization to move to Scrum, you can as an individual go compute your personal velocity right now.<span style="mso-spacerun: yes;"> </span>Any bug tracking system out there will allow you to gather data about the number of bugs assigned to you and/or fixed by you per unit time. If it were a database query you’d do something like “<i style="mso-bidi-font-style: normal;">select count(*) from bugs where assignee==”me” group by month(assignedDate)</i>”.<span style="mso-spacerun: yes;"> </span>Now, you may object saying “<i style="mso-bidi-font-style: normal;">but I do lots of other things besides fix bugs</i>”.<span style="mso-spacerun: yes;"> </span>You would<span style="mso-spacerun: yes;"> </span>likely be correct, and it still doesn’t matter.<span style="mso-spacerun: yes;"> </span>If a third of your time historically gets absorbed by mind numbing meetings what makes you think next month will be any different?</span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">All discussions of Black Swans aside, whatever last month looked like is a good starting point for guessing what next month might look like.<span style="mso-spacerun: yes;"> </span>By all means measure each month and look for trends.<span style="mso-spacerun: yes;"> </span>Perhaps you and/or your organization is getting better and your velocity is increasing.<span style="mso-spacerun: yes;"> </span>Now we have more confirmation of that fact.<span style="mso-spacerun: yes;"> </span>Or perhaps in response to missed deadlines you’re attending still more mind-numbing meetings to discuss such gems as why things take too long and so your velocity is decreasing.<span style="mso-spacerun: yes;"> </span>Cold comfort perhaps but now you have data to back up that dark realization.</span></div><br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">As an individual you might pick from several data sources to establish a velocity.<span style="mso-spacerun: yes;"> </span>The selection may depend on your job function (sustaining engineer, development engineer, etc) and/or on the systems you are using for bug tracking, source code management and the like.</span></div><br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">You might track the number of bugs fixed by you, the number of source code checkin’s you do, the number of code inspections you participated in or some combination of these and others.<span style="mso-spacerun: yes;"> </span>One interesting strategy is to gather the data from as many interesting sources as possible and then graph the results for longest time period that you have data for.<span style="mso-spacerun: yes;"> </span>If we assume that your actual theoretical velocity has been relatively constant you can select a data source or sources that results in a flat graph.<span style="mso-spacerun: yes;"> </span>Of course if you have switched languages or processes or problem domain your velocity likely has not been constant so your mileage may vary.</span></div>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-45337413762666674982012-04-17T10:29:00.000-07:002012-04-17T10:29:02.448-07:00Retrospective Velocity - Part 2 of 3<span style="font-family: Calibri;">One of the key take away messages from the experts in the field of estimation is not to estimate at all.<span style="mso-spacerun: yes;"> </span>To quote Steve McConnell: “ <i style="mso-bidi-font-style: normal;">If you can’t count the answer directly, you should count something else and then compute the answer by using some sort of calibration data</i>”.<span style="mso-spacerun: yes;"> </span>So, if we can’t count our velocity directly we <b style="mso-bidi-font-weight: normal;">can</b> count the number of bugs in our last project, how long they stayed open, how many requirements were present and so on.<span style="mso-spacerun: yes;"> </span>Our calibration data is that all of those requirements and bugs took place in the time interval of the project.<span style="mso-spacerun: yes;"> </span>It’s not especially fine grained but in a waterfall model we are not looking for fine grained data.</span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">Some may argue that bug reports and requirements are not precisely defined and standardized.<span style="mso-spacerun: yes;"> </span>What passes as a single requirement for one team might be 3-5 separate requirements for another team.<span style="mso-spacerun: yes;"> </span>Some teams have bugs like “it doesn’t work” while others might enter a dozen or more particular bugs to cover the same underlying defect.<span style="mso-spacerun: yes;"> </span>Here is the strange thing though: it doesn’t matter.</span></div><br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">Just like story points are not standardized, all that matters is that within your team you tend to be consistent.<span style="mso-spacerun: yes;"> </span>Whatever your team’s definition of a story point is if you’re doing Scrum is likely to represent about the same quantum of work next month that it represented last month.<span style="mso-spacerun: yes;"> </span>In the waterfall world,<span style="mso-spacerun: yes;"> </span>the level of granularity you bring to your bug reports is likely to be fairly constant.<span style="mso-spacerun: yes;"> </span>The point to keep in mind is that we’re not looking to equate points or bug counts against anything but other points and other bug counts.<span style="mso-spacerun: yes;"> </span>So, if your last several projects had 6 requirements, generated 60 bugs and took 6 months you have a velocity of 1 requirement and/or 10 bugs per month.<span style="mso-spacerun: yes;"> </span>If you next project arrives with 15 requirements and a deadline of three months from now we can safely conclude that you are in trouble!</span></div><br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">Keep in mind the distinction between accuracy and precision.<span style="mso-spacerun: yes;"> </span>In the proceeding case we can say with <b style="mso-bidi-font-weight: normal;">high</b> confidence that you are <b style="mso-bidi-font-weight: normal;">probably</b> hosed.</span></div>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-42396980969495529972012-04-16T11:27:00.000-07:002012-04-16T11:27:54.217-07:00Retrospective Velocity - Part 1 of 3<span style="font-family: Calibri;"><em>So how long is this going to</em> <em>take?</em><span style="mso-spacerun: yes;"> </span>This is one of the most common questions to ask or be asked in a traditional software development environment, and one of the most difficult to answer.<span style="mso-spacerun: yes;"> </span>The agile methodologies, and Scrum in particular address this problem with the notion of velocity.<span style="mso-spacerun: yes;"> </span>Whatever your team accomplished in the last time period (sprint) is likely similar to what they’ll be able to accomplish in the next one.<span style="mso-spacerun: yes;"> </span>Scrum’s use of burn down charts, standard definitions of “done” and retrospectives allows for the discovery of a team’s average velocity.<span style="mso-spacerun: yes;"> </span>One can argue about hours versus story points and many similar details but almost any implementation of Scrum allows for tracking how much work was done per unit time.</span><br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">Sadly, many projects are still using “traditional” methods (which seems to be one of the new names for waterfall).<span style="mso-spacerun: yes;"> </span>One of the drawbacks of this approach is that the time scales are relatively quite large compared to Scrum, which also means there are fewer time periods to measure.<span style="mso-spacerun: yes;"> </span>There is simply less data available is you have two six month buckets versus 12 one month buckets.<span style="mso-spacerun: yes;"> </span>This is one reason that “traditional” projects do not typically end up producing a team velocity.<span style="mso-spacerun: yes;"> </span>This in turns make it substantially challenging to estimate how long the next project will take.</span></div><br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: Calibri;">There is however other data that can be mined so as to uncover this more fine grained time measurements we are looking for.<span style="mso-spacerun: yes;"> </span>The data in question lives in your requirement tracking system, bug database and source code control system.<span style="mso-spacerun: yes;"> </span>While these systems are often, shall we say imprecise, they do contain useful data.</span></div>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-58718639857481204752012-03-07T09:00:00.000-08:002012-03-07T09:00:30.679-08:00Using QuickSort to Explore Scala Collection MethodsIn my continuing effort to play with my new favorite language Scala I decided to look at one of the Standard Algorithms in the field: quick sort. Quick Sort is a divide and conquer algorithm that picks a pivot point in a list and then calls itself to sort the two halves.<br />
<br />
<br />
StackOverflow.com demonstrated a very simple Scala quick sort shown below. Let’s examine it as a learning vehicle. The complex looking first line defines a function that takes a List of things T where T is any class that supports "Ordered". It also returns such a list.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHZdUpn7WHS324nyvaxNDoWylof7RsZZWtoigrMBJibHPhtIyM6GTN9YXqGe_QDfMiyDDjEqTxabsvMEEDFqeOcINEEoske1REORwIGp9XWVahzMJ_9xM-At10KRxNpbQh0PxQjm08gY8/s1600/Listing1.PNG" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHZdUpn7WHS324nyvaxNDoWylof7RsZZWtoigrMBJibHPhtIyM6GTN9YXqGe_QDfMiyDDjEqTxabsvMEEDFqeOcINEEoske1REORwIGp9XWVahzMJ_9xM-At10KRxNpbQh0PxQjm08gY8/s320/Listing1.PNG" width="320" yda="true" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
As with almost all recursive algorithms quick sort has two cases: the empty list and the non-empty list. Scala's "list match" sets up those two cases. In the case of the Nil list we return Nil which is how the recursive algorithm completes. Otherwise we match against "cdr::cons". That expression means "first item in the list followed by the rest of the list". Cons and cdr are the standard names that the Lisp language uses for those terms. This may seem like an odd way to view a list but in the functional world it is a very common idiom. <br />
<br />
<br />
So given a first element and a rest-of-the-list what do we do? We use another of Scala powerful collections function: partition. "cons partition (_ < cdr)" says "create two lists: a list of the items in the list that do match the condition and another list of the items that do not match the condition. These two lists are returned into the anonymous tuple “val (before after)”. This shows how Tuples are first class citizens in Scala, allowing us to return multiple values from a function call.<br />
<br />
Searching the web for Java implementations of quick sort shows the following code as quite typical for the partition portion of the algorithm:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMK6KPrwL39UjpADPXg0_GsJQV2gE-5QSsHMFBvod8eL8hLu6va_YrMMUVz16ee-2Lkf2fy12V5960ek8QkBOYfEEe5EVFlR4Ec2jpJfl6pgjYltWQSlgsG-M-VrrU1NeHIi9tKDu5RZw/s1600/Listing2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMK6KPrwL39UjpADPXg0_GsJQV2gE-5QSsHMFBvod8eL8hLu6va_YrMMUVz16ee-2Lkf2fy12V5960ek8QkBOYfEEe5EVFlR4Ec2jpJfl6pgjYltWQSlgsG-M-VrrU1NeHIi9tKDu5RZw/s320/Listing2.PNG" width="224" yda="true" /></a></div><br />
I don’t know about you but Listing 2 looks prime for off-by-one errors and is nothing I’d expect to get right the first time. Compare that to: val (before,after) = cons partition (_ < cdr). The beauty of that line is that its close to the English description: create lists of the items before and after the specified item by partitioning the list based on a test. I’m beginning to feel that Scala feels hard not because it is hard but because it’s so different from Java in that its easy! <br />
<br />
Lastly we have the recursive part of the function. We call ourselves on the before list and the after list, and build a new list of the results of those two calls plus the cdr value (because it’s not in either list). This implementation works and has the advantage of being a tiny bit of code. The drawback is that it always picks the first item in each list as the pivot point. It is known to be sub-optimal especially in the case where the function is called on an already sorted list.<br />
<br />
<div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: "Times New Roman", "serif"; font-size: 12pt; line-height: 115%;">This next version of the program picks a better pivot point, in this case the middle entry of the list.<span style="mso-spacerun: yes;"> </span>We accomplish this by changing the "<i style="mso-bidi-font-style: normal;">case</i>" to "<i style="mso-bidi-font-style: normal;">theList : List</i>" which just<span style="mso-spacerun: yes;"> </span>means any list.<span style="mso-spacerun: yes;"> </span>We manually find the pivot point and then perform two for-comprehensions to find the list items larger and smaller than the pivot entry.<span style="mso-spacerun: yes;"> </span>This gains performance via the better pivot point but trades that off against having to scan the main list twice for the two for-comprehensions.<span style="mso-spacerun: yes;"> </span>Further testing revealed that this implementation also had a defect in that if an item was present in the list more than once it would only appear once in the<span style="mso-spacerun: yes;"> </span>sorted output.<span style="mso-spacerun: yes;"> </span>Another reason for robust testing!</span></div><div class="separator" style="clear: both; text-align: center;"></div><span style="font-family: "Times New Roman", "serif"; font-size: 12pt; line-height: 115%;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpDHpg1s3T-UJFCgIYzCAn19g5I72g4CeUjAHiQWsES_Zk0pve1STxV0Te-DI4T-yECw9RrbZVh8O0IiLIsLVLZkPbpH7QouIwYMw0frYOmSGcUTtffw0xuHUMAXJG7LohDr33dtD1q-g/s1600/listing3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpDHpg1s3T-UJFCgIYzCAn19g5I72g4CeUjAHiQWsES_Zk0pve1STxV0Te-DI4T-yECw9RrbZVh8O0IiLIsLVLZkPbpH7QouIwYMw0frYOmSGcUTtffw0xuHUMAXJG7LohDr33dtD1q-g/s320/listing3.PNG" width="320" yda="true" /></a></div><div class="MsoNormal" style="margin: 0in 0in 10pt;"><br />
</div><div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: "Times New Roman", "serif"; font-size: 12pt; line-height: 115%;">Our last version (for now) tackles the duplicate issue and is also a bit more efficient. We go back to using partition to generate our two lists, but now we post-process the second list.<span style="mso-spacerun: yes;"> </span>We call partition again on the second list (which contains items not-less-than the pivot) into a list of matching items and not matching items. </span></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiek6SLz5HHrDL6SINvVPtJDyV9jyL-hTSG43KCEMfaJQSt8CFJ05RyXpz7PmDGUru2JNtgsi0wl3GVpxI50QZz8iFmB-ilepO_e-4lKnc5FCyU5MkRmGm3ZLvNKMBZsUcLhhePAwna3QE/s1600/Listing4.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiek6SLz5HHrDL6SINvVPtJDyV9jyL-hTSG43KCEMfaJQSt8CFJ05RyXpz7PmDGUru2JNtgsi0wl3GVpxI50QZz8iFmB-ilepO_e-4lKnc5FCyU5MkRmGm3ZLvNKMBZsUcLhhePAwna3QE/s320/Listing4.PNG" width="320" yda="true" /></a></div><div class="MsoNormal" style="margin: 0in 0in 10pt;"><br />
</div><div class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="font-family: "Times New Roman", "serif"; font-size: 12pt; line-height: 115%;"><strong>Summary</strong>: This article is not meant to create the best possible Scala implementation of<span style="mso-spacerun: yes;"> </span>Quick Sort, but to give you a vehicle for playing with Scala list manipulation functions.</span></div><div class="MsoNormal" style="margin: 0in 0in 10pt;"><br />
</div></span>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-64078448118377075302012-01-27T08:14:00.000-08:002012-02-02T07:06:10.484-08:00Scala version of Log4JFugue, plus revamped websiteOver the recent holidays I decided to create a Scala version of my Log4JFugue open source music project. I was able to reduce the 2500 lines of Java to just over 250 lines of Scala!<br />
<br />
Checkout the new <a href="http://www.log4jfugue.org">www.log4jfugue.org</a> as well as: <br />
<a href="http://github.com/btarbox/Log4ScalaFugue">Scala sources</a><br />
<br />
I'll be giving a talk on the experience of converting a small Java project to Scala at the March meeting of <a href="www.nejug.org">New England Java User's Group</a>.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com2tag:blogger.com,1999:blog-362788945979237212.post-65226789295706834572011-12-07T10:07:00.000-08:002011-12-07T10:07:57.503-08:00new article in December PragProg magazineI just had an article published in the December Pragmatic Programmer magazine on <a href="http://pragprog.com/magazines/2011-12/justintime-logging"><br />
a new approach to logging</a>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-83155899568301149472011-11-18T08:47:00.000-08:002011-11-18T08:47:35.254-08:00Writing on a TabletI do a lot of writing these days, some on my high end Windows laptop with dual 20 inch monitors and some on my 10 inch tablet with Bluetooth keyboard.<br />
<br />
I have surprisingly discovered that I am far more efficient on the tablet. This is surprising because on the tablet I have much smaller screen (less than 100 square inches versus more than 700 square inches), I don’t have a mouse, and switching from my writing app to email or the web is more involved.<br />
<br />
That last item proves to be the key item. Because the tablet is primarily not a multitasking device I tend to focus on writing when I’m writing. The lure of the emails lurking in my system tray is gone. The other browser windows in my giant multimonitor display do not call to me. The fact that my tablet can really only do one thing at time is not a limitation it is a benefit.<br />
<br />
While at a certain level this is obvious it’s also interesting given the current debates about multitasking operating systems. At the same time that some OSs are claiming to be better because of multitasking some of the mainstream OSs are adding features to discourage multitasking! For example various flavors of Linux have the option to automatically dim all windows other than the active one. The idea is to reduce the lure of context switching.<br />
<br />
All kinds of current research is showing that humans cannot really multitask, yet we want to pretend that we can. At the same time, we know that the key to writing is to…well…write. And as much as we love to write we also love anything that can distract us from writing. So using a “limited” system to do our writing on is really to our advantage.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-33922724951152729472011-11-16T09:15:00.000-08:002011-11-16T09:15:09.350-08:00A few minutes with the Kindle FireI got to spend a few minutes with the Kindle Fire yesterday. Full disclosure: we have two kindles, an iPad, a smartphone and assorted laptops at home.<br />
<br />
The iPad has almost completely replaced the laptop at home, and with a bluetooth keyboard I do most of my writing on it. It comes with me to the numerous evening Meetups I attend.<br />
<br />
My kindle comes with me everywhere during the day, because it fits in my pocket which lets me squeeze in lots of spare minutes reading.<br />
<br />
The smartphone has been relegated to making phone calls and checking gmail when out of wifi.<br />
<br />
The KF is agreeably small and light and I could imagine it being with me everywhere. The screen is clean and crisp. Some reviewers have complained about slow screen response but I did not encounter that. Page turns while reading were very responsive and selecting items from the various menus was easy.<br />
<br />
The touch screen made selecting and highlighting text much simpler than on the legacy kindle, so I might pick the KF for technical reading where I do lots of note taking.<br />
<br />
One problem I did encounter was in getting to the menu screen. Most apps are full screen so to get to the menu and the Home button you have to touch the bottom of the screen. The location to touch was hard to find. It often took me lots of touches to bring up the menu resulting in lots of unwanted page turns. Presumably this would be something one would figure out over time.<br />
<br />
Movies look nice on the KF, though obviously a smaller image than on the iPad. My kindle reading is largely opportunistic, a few minutes here and there. While I'm willing to read books a page at time I don't know that I'd want to watch a movie that way. When I know I might have blocks of time I bring my iPad. So movies wouldn't be a KF draw for me though they might be for my iPad-less wife.<br />
<br />
Magazines look much better on the KF than on the legacy kindle.<br />
<br />
In the end buying a KF or not depends on what devices you already have and what you want to do.<br />
If you just have a legacy kindle or a smartphone and don't want to do content creation the KF makes sense. If you just have a iPad but no book reader you might get the KF for its extra portability.<br />
<br />
For my wife who has a kindle plus dumb phone and wants some internet access we have a couple of choices. We could get a $300 smart phone plus two years of a $30/month add-on data plan; two year cost $1020. Or a $200 KF, possibly adding on the $79/year Amazon Prime membership. That seems like an easy choice for us. Your mileage may vary.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-30341962842331521362011-11-03T06:29:00.000-07:002011-11-03T06:33:04.148-07:00New article published at Pragmatic ProgrammersI just had an article published in the Pragmatic Programmer magazine on <a href="http://pragprog.com/magazines/2011-11/root-cause-analysis-from-long-ago"><br />the long history of root cause analysis</a>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com0tag:blogger.com,1999:blog-362788945979237212.post-78514223785035218992011-09-30T08:08:00.000-07:002011-09-30T08:09:14.030-07:00Kindle Fire replaces SmartPhone not tabletJust had a conversation with my wife about the Kindle-Fire (KF) and had an epiphany.<br /><br />KF isn't a replacement for the full tablet, but it is a replacement for the smart phone!<br /><br />KF costs $200 plus zero for service contract<br />smart phone costs $50-$200 plus at least $30 a month for data contract.<br /><br />If you mostly use the 'smart' features of the phone for things like email/calendar/games, then it may be very compelling to ditch the cellular data plan, ditch the smart phone, get a dumb phone for making dare-I-say-it phone calls and the KF for email/calendar/etc.<br /><br />I think we're going to do that.<br /><br />OTOH, if you want a tablet for creating rather than consuming content, you still need a full size tablet, preferably with a keyboard.Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com1tag:blogger.com,1999:blog-362788945979237212.post-33311769739906494382011-09-14T06:21:00.000-07:002011-09-14T06:48:36.684-07:00Publication SummaryI've been asked a few times for a summary of my publications over the last few years so here it is. <br /><br /><a href="http://pragprog.com/magazines/2011-09/scala-traits">Sept 2011 Scala Traits </a><br /><br /><a href="http://pragprog.com/magazines/2011-08/code-as-dialog">August 2011 Code As Dialog </a><br /><br /><a href="http://pragprog.com/magazines/2011-05/catch-the-pig">May 2011 Catch the Pig! </a><br /><br /><a href="http://rubylearning.com/blog/2010/10/25/the-value-of-a-personal-bug-log"/> November 2010 The value of a personal bug log</a>"<br /><br /><a href="http://pragprog.com/magazines/2010-09/the-key-to-better-software">September 2010 The Key to Better Software </a><br /><br /><a href="http://pragprog.com/magazines/2010-06/better-tools-and-training">June 2010 Better Tools and Training </a><br /><br /><a href="http://drdobbs.com/database/218100564?fmid=12269">June 2010 Debugging MySQL Stored Procedures </a><br /><br /><a href="http://pragprog.com/magazines/2010-05/the-floating-finish-line">May 2010 The Floating Finish Line </a><br /><br /><a href="http://pragprog.com/magazines/2010-04/medicine-making-music">April 2010 Medicine Making Music </a><br /><br /><a href="http://pragprog.com/magazines/2010-03/testing-as-contract">March 2010 Testing As Contract </a><br /><br /><a href="http://pragprog.com/magazines/2009-11/interrupt-mood">November 2009 Interrupt Mood </a><br /><br /><a href="http://pragprog.com/magazines/2009-09/and-your-bugs-can-sing">June 2009 ...And Your Bugs Can Sing </a>Brian Tarboxhttp://www.blogger.com/profile/11506285455540985587noreply@blogger.com2