<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Flurry Tech Blog</title>
	
	<link>http://flurrytechblog.wordpress.com</link>
	<description>Technology lessons from the cutting edge of mobile and big data.</description>
	<lastBuildDate>Fri, 24 May 2013 18:25:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain="flurrytechblog.wordpress.com" port="80" path="/?rsscloud=notify" registerProcedure="" protocol="http-post" />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Flurry Tech Blog</title>
		<link>http://flurrytechblog.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://flurrytechblog.wordpress.com/osd.xml" title="Flurry Tech Blog" />
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/FlurryTechBlog" /><feedburner:info uri="flurrytechblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://flurrytechblog.wordpress.com/?pushpress=hub" /><item>
		<title>Source Code Analyzers as a Development Tool</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/5z1RhQ6Z8aE/</link>
		<comments>http://flurrytechblog.wordpress.com/2013/05/24/source-code-analyzers-as-a-development-tool/#comments</comments>
		<pubDate>Fri, 24 May 2013 18:24:12 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://flurrytechblog.wordpress.com/?p=176471809</guid>
		<description><![CDATA[It is difficult to write consistent and high quality code when using libraries/sdks from multiple sources and when development is distributed between several teams and multiple time zones.  Many challenges exist for both new and experienced developers including lack of documentation, insufficient unit test coverage and nuances to each platform/sdk that make things different. It [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=176471809&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p dir="ltr">It is difficult to write consistent and high quality code when using libraries/sdks from multiple sources and when development is distributed between several teams and multiple time zones.  Many challenges exist for both new and experienced developers including lack of documentation, insufficient unit test coverage and nuances to each platform/sdk that make things different. It becomes necessary for developers of one platform to understand complicated legacy code of an unfamiliar platform. To make things more complex, it may be written in a language they do not understand well.  It is estimated that upto 60-80% of programmer’s time is spent to maintain a system and 50% of that maintenance effort is spent understanding that program (<a href="http://www.bauhaus-stuttgart.de/bauhaus/index-english.html" rel="nofollow">http://www.bauhaus-stuttgart.de/bauhaus/index-english.html</a>).</p>
<p dir="ltr">It is helpful for developers to have  tools that can analyze different codebases quickly. A rather comprehensive list of source code analyzer tools for each platform is listed here: (<a href="http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis" rel="nofollow">http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis</a>) .  Since an in-depth comparison of the multitude of analyzer tools is beyond the scope of this article, all figures and analysis were done by using Understand by Scitools, a typical albeit premium source code analysis tool.</p>
<p dir="ltr"><strong>Understand by SciTools</strong></p>
<p dir="ltr">Understand by SciTools has the ability to scan Ada, Cobol, C/C++, C#, Fortran, Objective-C, Java, Jovial, Pascal, PL/M, Python and others. Like many multi-language analyzer programs it is not free, however, the benefits of such a program are enormous. (For the purposes of this demonstration, a deprecated and unused codebase was analyzed.)</p>
<p dir="ltr">After source code files have been parsed, you’ll see multi-windowed view like the following:<img alt="" src="https://lh4.googleusercontent.com/Rq9vRdPPz4GYzC-ORZamyVpgD037OAGH3kq3_4C03A9e1FXvcfBdKhqhjU4F_1VGr2jbSs7JDXHIbrkkK8xJWlVdp7d85Da-O1OubngM-Ofl4OFT0fQ-cUE15Q" width="557px;" height="305px;" /></p>
<p dir="ltr">Figure 1. Parsing of project sources</p>
<p dir="ltr"><img alt="" src="https://lh4.googleusercontent.com/XDAz_HPqKcubpiFSTClIVWQAyom7O7Y-csv6gQrt8IqUY9Wgco2ymIo_Ftw4-5GBe1xTqCw_aTeQAZ8xNfzRHXk-8twGowaalN5gMQuWIsHEFFJOvGqUDpqtgA" width="623px;" height="295px;" /></p>
<p dir="ltr">Figure 2. IDE source windows.</p>
<p dir="ltr"><strong>Pros of Source Code Analyzer tool</strong></p>
<p dir="ltr">The ability to see how a variable/method in the project is analyzed, how it is used (or unused) in the project, what methods call it or what methods are called by it are a quick way to get reference information. This can also be done quite easily in various IDEs of the respective languages &#8211; Xcode, Eclipse, IntelliJ, etc. What sets premium multi-language source code analysis tools apart from IDEs is the ability to see graphically how the source code is structured and to be able to run metrics on them as a whole.  In Figure 3, for example, we notice that the androidTestApp has 113 references to the androidAdAgent library. The flurryAdTestApp has about 25 dependencies on such project. Further analysis of this project reveals that the flurryAdTestApp is a generic sample project for testing ad functionality while the androidTestApp is a more universal testing application. There are many more benefits to know this internal dependencies &#8211; for example, knowing how complex a dependency exists makes it easier to understand how much QA is required if such code is refactored.</p>
<p dir="ltr"><img alt="" src="https://lh3.googleusercontent.com/ZYgPPiUfyqHB4FzRJU_CEF7iJXCyiEX5sDn76RmBIBO94JL2RjHPfjsuHESIDBd_ppGP5Gs_ezHc9hGQF1GZPVDQje7RifUZ7_0VNAlWtjWi2phn9XxVhYeuCQ" width="606px;" height="321px;" /></p>
<p dir="ltr">Figure 3. Internal architecture complexity</p>
<p dir="ltr"><img alt="" src="https://lh6.googleusercontent.com/h5cah3c6YU4EyXrN30PqIfjZ1BNCBOuKqxR6nMNYurpuCWnXAmuNGf_2bIP5NRdJ0Eu2XrlsEkQTd59j2IJFxoEjrgTTxDh73qhnf3Q-ZU8k0dZTxOZlDX-_Qw" width="585px;" height="336px;" /></p>
<p dir="ltr">Figure 4. UML class diagram</p>
<p dir="ltr">Figure 4 shows the overall UML class structure of the project. This is particularly useful if you need to refactor or re-engineer your code base to specific design patterns. Some of these analyzer tools allow you to directly manipulate the uml diagrams and the underlying code structure is changed as a result.</p>
<p dir="ltr"><img alt="" src="https://lh5.googleusercontent.com/OffiA7ihiXLmGuZEQtK1SJPOV60LtFTxYHrMAVkpI14Kw0hBGuxGQCv1BWDqD1Kloox5u4tWMeT0ajR-KPcMbT9oSJ_PVhDD3suhyT_MF9QhCjCpwROu0GFlsA" width="507px;" height="282px;" /></p>
<p dir="ltr">Figure 5. Unused variables and parameters</p>
<p dir="ltr">The ability to see unused variables and parameters is particularly useful in reducing code bloat and keeping the codebase lean.</p>
<p dir="ltr"><img alt="" src="https://lh4.googleusercontent.com/nX53E5YPd-oIKp76E-Kg2NbejjZw6lX07DGtKgGSXSA6ph35f79McKTcWEDg0-MEoc53xDLMr4kshjWN3jO9ubHrXx-wT6czLU5oP7Zr-5s7HMP1JW5aUaGRyA" width="622px;" height="382px;" /></p>
<p dir="ltr">Figure 6. Check code for various coding standards.</p>
<p dir="ltr">Quite a few of these premium analyzer tools have code check algorithms that allow you to be notified of overly complex algorithms (big-O, number of lines, cyclomatic dependencies, and unused code paths). Overly complex programs are difficult to comprehend and have many possible paths making them difficult to test and validate. Most analyzer tools allow you to record/program your own macros for determining proper code validation:</p>
<p dir="ltr">- Improper use of .equals() and .hashCode()</p>
<p dir="ltr">- Unsafe casts</p>
<p dir="ltr">- When something will always be null</p>
<p dir="ltr">- Possible StackOverflows</p>
<p dir="ltr">- Possible ignored exceptions</p>
<p dir="ltr">- Cyclomatic Compexity (modified, strict)</p>
<p dir="ltr">Cons of Source Code Analyzer tool</p>
<p dir="ltr">One drawback of using such source code analysis tools is that you have to configure the project to find all relevant sources for each project type – Failure to have a project properly configured could result in too much or too little detail that’s useful. Source code that is significantly modular across libraries would be difficult to analyze.  Also, many tools that are out there are quite one-dimensional in that they may check coding style but may not be able to provide detailed analysis on code complexity and improper algorithmic complexity. One open source tool that shows promise is sonar (<a href="http://www.sonarsource.org">http://www.sonarsource.org</a>) but it’s big drawback is that it requires a web server and a database. Other possible issues are that some code analyzers analyze the bytecode while others analyze the source. Whatever source analyzer tool is chosen it may not be comprehensive enough for the organizational needs.</p>
<p dir="ltr">At Flurry, we have multiple sdk codebases &#8211; Objective-C, java (android), BlackBerry10, windows phone 8/7, windows 8, HTML5. Each additional analyzer tool needs a significant learning curve. We try to keep the tools to a minimum while still trying to get coverage on the different codebases.</p>
<p dir="ltr">Source Code Analysis As Part of the Development Environment</p>
<p dir="ltr">There are many programs that analyze source code but only few provide support for multiple languages and are open-source. The most popular ones for java are PMD, FindBugs and Checkstyle.  However a tool that is simple, multi-language and open-source would be ideal.</p>
<p dir="ltr">The ability to easily see the UML structure of a program, understand it’s code complexity, and see all the dependencies with the click of a button can easily replace invalid comments and outdated documentation. A good source analyzer tool is only one part of a toolbox that should be available to the developer. Unit tests, code reviews, and pair programming should always have priority but a source code tool can definitely help the developer (both new and experienced) to keep track of large codebase that he may be working on.</p>
<p dir="ltr">
<p dir="ltr"><em>Author: Richard Brett</em></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/176471809/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/176471809/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=176471809&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=5z1RhQ6Z8aE:eD27byABpIQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=5z1RhQ6Z8aE:eD27byABpIQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/5z1RhQ6Z8aE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2013/05/24/source-code-analyzers-as-a-development-tool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>

		<media:content url="https://lh4.googleusercontent.com/Rq9vRdPPz4GYzC-ORZamyVpgD037OAGH3kq3_4C03A9e1FXvcfBdKhqhjU4F_1VGr2jbSs7JDXHIbrkkK8xJWlVdp7d85Da-O1OubngM-Ofl4OFT0fQ-cUE15Q" medium="image" />

		<media:content url="https://lh4.googleusercontent.com/XDAz_HPqKcubpiFSTClIVWQAyom7O7Y-csv6gQrt8IqUY9Wgco2ymIo_Ftw4-5GBe1xTqCw_aTeQAZ8xNfzRHXk-8twGowaalN5gMQuWIsHEFFJOvGqUDpqtgA" medium="image" />

		<media:content url="https://lh3.googleusercontent.com/ZYgPPiUfyqHB4FzRJU_CEF7iJXCyiEX5sDn76RmBIBO94JL2RjHPfjsuHESIDBd_ppGP5Gs_ezHc9hGQF1GZPVDQje7RifUZ7_0VNAlWtjWi2phn9XxVhYeuCQ" medium="image" />

		<media:content url="https://lh6.googleusercontent.com/h5cah3c6YU4EyXrN30PqIfjZ1BNCBOuKqxR6nMNYurpuCWnXAmuNGf_2bIP5NRdJ0Eu2XrlsEkQTd59j2IJFxoEjrgTTxDh73qhnf3Q-ZU8k0dZTxOZlDX-_Qw" medium="image" />

		<media:content url="https://lh5.googleusercontent.com/OffiA7ihiXLmGuZEQtK1SJPOV60LtFTxYHrMAVkpI14Kw0hBGuxGQCv1BWDqD1Kloox5u4tWMeT0ajR-KPcMbT9oSJ_PVhDD3suhyT_MF9QhCjCpwROu0GFlsA" medium="image" />

		<media:content url="https://lh4.googleusercontent.com/nX53E5YPd-oIKp76E-Kg2NbejjZw6lX07DGtKgGSXSA6ph35f79McKTcWEDg0-MEoc53xDLMr4kshjWN3jO9ubHrXx-wT6czLU5oP7Zr-5s7HMP1JW5aUaGRyA" medium="image" />
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2013/05/24/source-code-analyzers-as-a-development-tool/</feedburner:origLink></item>
		<item>
		<title>Interview Strategies at Flurry</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/MenzGcpkNjk/</link>
		<comments>http://flurrytechblog.wordpress.com/2013/04/03/interview-strategies-at-flurry/#comments</comments>
		<pubDate>Wed, 03 Apr 2013 17:56:00 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/interview-strategies-at-flurry</guid>
		<description><![CDATA[To meet the demands of the market, Flurry has grown rapidly. Our numbers have roughly doubled each year, and we plan to continue this trajectory for the foreseeable future. Because of this pattern, we spend a significant amount of time interviewin...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=176471746&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">To meet the demands of the market, Flurry has grown rapidly. Our numbers have roughly doubled each year, and we plan to continue this trajectory for the foreseeable future. Because of this pattern, we spend a significant amount of time interviewing candidates. Here is our approach.</span></strong></strong></p>
<p style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><br /></span></strong></strong></p>
<p style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Synopsis</span></strong></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;">
<div class='p_embed p_image_embed'><img alt="Untitled" height="85" src="http://flurrytechblog.files.wordpress.com/2013/04/untitled-scaled500.jpg?w=462&#038;h=85" width="462" /></div>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Our process is designed to help us discover as much as we can about each candidate as efficiently as possible. We begin with a phone screen, which is a low effort, low cost handshake between us and the candidate. This gives us a basic sense of their programming knowledge and their compatibility with us. Then, we follow up with a code test that evaluates their ability to design and implement a solution to the proposed challenge. Finally, we conduct two onsite interviews, one of which covers the design decisions made in their code test and their technical abilities, and another which covers their creative problem solving skills and delves into their past experiences.</span></strong></strong></strong></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">During the two interviews, we assess the following:</span></strong></strong></p>
<ul style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"> </strong></strong>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">Communication skills</span></p>
</li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">Problem solving skills</span></p>
</li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">Design ability</span></p>
</li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">Team fit</span></p>
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;"><br /></span></p>
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;"><br /></span></p>
</li>
</ul>
<p style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Giving Hints</span></strong></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"> </strong></strong></p>
<p style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Most candidates will get stuck solving a problem at least once during the interviews. This is our opportunity to direct the conversation with a hint. A good hint can sometimes be very difficult to give. If an interviewee has chosen to answer a problem solving question in a way that is unusual but not necessarily incorrect, and then gets stuck, it is up to us to think ahead and supply a hint that helps them get to where they want to go. This can be especially challenging if the interviewee knows more about the subject than we do. The alternative is to give a hint that sets the candidate onto a path that leads to a known good solution, but this has several drawbacks. First, it wastes time because the interviewee must start again. Second, the candidate often still has their original idea in mind, which distracts them. Finally, pointing someone in a completely different direction is jarring and throws them off, especially if they start analyzing whether they have jeopardized their chances at an offer by getting the question wrong. Ideally, a good hint will provoke a thoughtful discussion about how to arrive at a solution. This also introduces a collaborative element to the interview and gives the interviewee a chance to teach us something. By digging in like this, we gain a wealth of information about their ability to communicate and how they approach problems.</span></strong></strong></p>
<p>&nbsp;</p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Reviewing the Code Test</span></strong></strong></p>
<p style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">The code test tells us several things about the candidate:</span></strong></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"> </strong></strong></p>
<ul style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"> </strong></strong>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">How they write code in a natural setting</span></p>
</li>
</ul>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"> </strong></strong></p>
<ul style="margin-top:0;margin-bottom:0;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"></strong></strong>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">How they structure blocks of code &ndash; is it organized into logical units of work?</span></p>
</li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">How they test their code &#8211; are their tests concise and relevant? What do the tests cover? Is their code designed to be testable?</span></p>
</li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">
<p style="margin-top:0;margin-bottom:0;"><span style="background-color:transparent;vertical-align:baseline;">How they design their algorithms &#8211; what approach does the candidate take?</span></p>
</li>
</ul>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><strong style="font-weight:normal;"> 
<p style="margin-top:0;margin-bottom:0;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Reviewing the test with the candidate mimics an actual code review. We discuss the compromises they made, such as performance, readability, and testability. We also explore the design decisions the candidate made to gain insight into how they prioritize their development practices. This also gives us a sense of how they respond to feedback: do they give justifications for their design decisions? Do they readily acknowledge mistakes?</span></p>
<p>
<p style="margin-top:0;margin-bottom:0;">&nbsp;</p>
<p style="margin-top:0;margin-bottom:0;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Digging Deeper</span></p>
<p>
<p style="margin-top:0;margin-bottom:0;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Any candidate can memorize the answers to common interview questions, but eliciting such canned responses will not give us useful information about their abilities as a programmer. Therefore, we choose questions that lead to interesting discussion. For a hypothetical example, take the simple question of &ldquo;What is a tree set?&rdquo; If the candidate talks about the O(log n) find/insert/remove operations, we could follow up with &ldquo;Since a tree is faster than a linked list for common operations, what are some reasons to use a linked list instead of a tree set?&rdquo; This forces the candidate to explain their thought process, which is much more valuable than knowing whether the candidate can regurgitate runtime efficiencies of common structures.</span></p>
<p>
<p style="margin-top:0;margin-bottom:0;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Listening Well</span></p>
<p>
<p style="margin-top:0;margin-bottom:0;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">At Flurry, we care about a candidate&rsquo;s communication skills and fit just as much as their technical abilities. We pick up that information in a few ways. A lot of this type of information is gleaned during the technical portions. If a technical question is too hard or unexpected, we can look at an interviewee&rsquo;s coping mechanisms &ndash; do they panic? What is their thought process &ndash; does it jump around or does it logically build from a set of premises? If a question is too easy, how does the candidate respond? Is he arrogant or dismissive? These are the keys which will tell us if an interviewee is confident about what they know and don&rsquo;t know and is able to think for themselves. This kind of information can come from anywhere at any time, so we make sure to stay and take notes regardless of what it happening. By the end of the process, several different interviewers must come to a single conclusion, and if anybody thinks the candidate is not qualified, we pass on them.</span></p>
<p>
<p style="margin-top:0;margin-bottom:0;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Describing Flurry to the Interviewee</span></p>
<p>
<p style="margin-top:0;margin-bottom:0;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Anyone familiar with the process knows that interviews are just as much about helping the candidate learn about the company as they are evaluating the candidate. Since Flurry values intelligence and honesty, we want to attract the same qualities in our candidates. To that end, during the interview process, we are truthful about Flurry&rsquo;s strengths and weaknesses and present a clear picture of what it will be like working here. The people interviewing the candidate are their future colleagues, and interviews take place in the same location as their future work environment. By the end of it, a candidate should have a good idea what it is like to work here, should they accept an offer. </span></p>
<p /></strong></strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="color:#c0c0c0;"><em>Author: Jon Miller</em></span></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/176471746/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/176471746/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=176471746&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=MenzGcpkNjk:6kc0pOPw-YA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=MenzGcpkNjk:6kc0pOPw-YA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/MenzGcpkNjk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2013/04/03/interview-strategies-at-flurry/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2013/04/untitled-scaled500.jpg" medium="image">
			<media:title type="html">Untitled</media:title>
		</media:content>
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2013/04/03/interview-strategies-at-flurry/</feedburner:origLink></item>
		<item>
		<title>APNS Test Harness</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/fe7xowIhIQ4/</link>
		<comments>http://flurrytechblog.wordpress.com/2013/02/14/apns-test-harness/#comments</comments>
		<pubDate>Thu, 14 Feb 2013 00:25:00 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/apns-test-harness</guid>
		<description><![CDATA[As Dr. Evil found out after spending a few decades in a cryogenic freezer, perspectives on quantity change very quickly. Ever since the explosion of mobile apps and the growing number of services that can deal with humongous amounts of data, we ne...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=175292942&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">As Dr. Evil found out after spending a few decades in a cryogenic freezer, perspectives on quantity change very quickly. Ever since the explosion of mobile apps and the growing number of services that can deal with humongous amounts of data, we need to re-define our concepts of what &lsquo;Big Data&rsquo; means. This goes for developers who want to write the Next Great App, as well as those who want to write services to support it. </span></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">One of the best ways of connecting with mobile application customers is via remote push notifications. This is available on both Android (GCM) and iOS (APNS). These services allow developers to send messages directly to their users and this is an extremely valuable tool to announce updates, send personalized messages and engage directly with the audience. Google and Apple provide services that developers can send push messages to and they in turn deliver those messages to their users. </span></strong></p>
<p>
<div class='p_embed p_image_embed'><img alt="Drevilpush" height="400" src="http://flurrytechblog.files.wordpress.com/2013/02/drevilpush-jpeg-scaled500.jpg?w=400&#038;h=400" width="400" /></div>
</p>
<p><strong><span style="font-family:Arial;"><span style="font-size:15px;">The Problem</span></span></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">It&rsquo;s not unusual for apps these days to have in the order of millions and even tens of millions of users. Testing a Push Notification backend can be extremely hard. Sure, you can set up a few test devices to receive messages but how do you know how long it would take your backend to send out a large number of push messages to the Google and Apple servers? Also, you don&rsquo;t want to risk being throttled or completely blacklisted by either of those services by sending a ton of test data their way. </span></strong></p>
<p><strong><span style="font-family:Arial;"><span style="font-size:15px;">The Solution</span></span></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">The solution is to write a mock server that&rsquo;s able to simulate the Google/Apple Push Notification Service, and a test client to hit it with requests.</span></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">The Google service is completely REST based, so a script that executes a lot of curls in a loop can do that job. Also, it&rsquo;s fairly straightforward to write a simple HTTP server and accepts POSTs and sends back either a 200 or some sort of error code. </span></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Apple&rsquo;s APNS, however, presents a few challenges. It&rsquo;s a binary format listed <a href="http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW4" target="_blank">here</a>. </span></strong><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Since the protocol is binary, you need to write some sort of mock client that can generate messages in the specified format. At Flurry, we&rsquo;ve been playing around with Node.js to build scalable services and it&rsquo;s fairly straightforward to setup an Apple APNS test client and server.</span></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><strong style="font-family:Arial, Helvetica, sans-serif;font-size:13px;"><span style="font-family:Arial;"><span style="font-size:15px;">The Client</span></span></strong></span></strong></p>
<p><a href="https://gist.github.com/rahuloak/4949310">https://gist.github.com/rahuloak/4949310</a></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">The client.connect() method connects to the mock server and generates test data. The Buffer object in Node is used to pack the data into a binary format to send it over the wire. Although the protocol lets you specify a token size, the token size has been set to 64 bytes in the client since that&rsquo;s typically the token length that gets generated. Also, in our experience, the APNS server actually rejects tokens that aren&rsquo;t exactly 64 bytes long. The generateToken() method generates 64 byte hex tokens randomly. The payload is simple and static in this example. The createBuffer method can generate data in both the simple and enhanced format. </span><br /><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">&nbsp;</span><br /><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">What good is a client without a server, you ask? So without further ado, here&rsquo;s the mock server to go with the test client.</span></strong></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><strong style="font-family:Arial, Helvetica, sans-serif;font-size:13px;"><span style="font-family:Arial;"><span style="font-size:15px;">The Server</span></span></strong></span></strong></span></strong></p>
<p><a href="https://gist.github.com/rahuloak/4949381">https://gist.github.com/rahuloak/4949381</a></p>
<p><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><strong style="font-family:Times;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">After accepting a request, the server buffers everything into an array and then reads the buffers one by one. APNS has an error protocol, but this server only sends a 0 on success and a 1 otherwise. Quick caveat: Since the server stores data in a variable until it gets a FIN from the client (on &lsquo;end&rsquo;) and only then does it process the data, the {allowHalfOpen:true} option is required on createServer so that the client does not automatically close the connection. </span>
<p /><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">This setup is fairly basic, but it is useful for many reasons. Firstly, the client could be used to generate fake tokens and send them to any server that would accept them (just don&rsquo;t do it to the APNS server, even in sandbox mode). The data in the payload in the above example is static, but playing around with the size of the data as well as the number of blocks sent per request helps identify the optimal size of data that you would want to send over the wire. At the moment, the server does nothing with the data, but saving it to some database or simply adding a sleep in the server would be a good indicator of estimated time to send a potentially large number of push messages. There are a number of variables that could be changed to try and estimate the performance of the system and set a benchmark of how long it would take to send a large batch of messages. </span>
<p /><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Happy testing!</span></strong></span></strong></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/175292942/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/175292942/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=175292942&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=fe7xowIhIQ4:gzHIpZqsD4Y:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=fe7xowIhIQ4:gzHIpZqsD4Y:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/fe7xowIhIQ4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2013/02/14/apns-test-harness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2013/02/drevilpush-jpeg-scaled500.jpg" medium="image">
			<media:title type="html">Drevilpush</media:title>
		</media:content>
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2013/02/14/apns-test-harness/</feedburner:origLink></item>
		<item>
		<title>Tech Women</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/lLZYv6_ZPVU/</link>
		<comments>http://flurrytechblog.wordpress.com/2013/01/22/tech-women/#comments</comments>
		<pubDate>Tue, 22 Jan 2013 02:24:00 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/tech-women</guid>
		<description><![CDATA[4th grade budding girl geek in the making 2nd row 2nd girl from the left I grew up in a small suburb of New York fascinated with math and sciences. 3-2-1 Contact was my all-time favorite show then and getting their magazine was such a joy. As a yo...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=174414955&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<div>
<div style="text-align:center;"><strong style="font-size:medium;font-family:Times New Roman;font-weight:normal;"><img src="https://lh6.googleusercontent.com/kUMkblIbulk6WnaTKXo_sEEO4_XEIw4YbAGRJnjAgGOEMvq9k4NdAJkt8nWjXsx_2tW4Sz8MVYF0sP_X_NiZ4pM8ODdmLM3nnuBhg6ul6yN-cz1McHY" height="405px;" alt="" width="573px;" /></strong></div>
<p><strong style="font-size:medium;font-family:Times New Roman;font-weight:normal;"> </strong>
<p style="text-align:center;margin-top:0;margin-bottom:0;"><span style="font-size:11px;font-family:Arial;background-color:transparent;vertical-align:baseline;">4th grade budding girl geek in the making 2nd row 2nd girl from the left</span></p>
</div>
<div><span style="font-size:11px;font-family:Arial;background-color:transparent;vertical-align:baseline;">&nbsp;</span><br /><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">I grew up in a small suburb of New York fascinated with math and sciences. 3-2-1 Contact was my all-time favorite show then and getting their magazine was such a joy. As a young girl it was fun to try out the BASIC programs they published, programming with a joystick and running them on my Atari system (Yes programming with a joystick or paddle is just as useful as the</span><a href="http://youtu.be/9BnLbv6QYcA" target="_blank"><span style="vertical-align:baseline;font-size:15px;background-color:transparent;text-decoration:initial;font-family:Arial;"> </span><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">MacBook Wheel</span></a><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">.) It seemed like a no brainer to dive into computers when I started college. Women in my family were commonly in the sciences, so entering my college CS program was a bit of a culture shock for me; I could actually count all the women in my class year on one hand!</span><br /> <span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">&nbsp;</span><br /><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">After graduating and working at a range of tech companies as a Quality Assurance Engineer, from big players to small startups, I&#8217;ve always had the desire to give back to the tech community. Only recently, however, did I find the right avenue. One day a co-worker of mine shared a link with me about the</span><a href="http://www.techwomen.org/" target="_blank"><span style="vertical-align:baseline;font-size:15px;background-color:transparent;text-decoration:initial;font-family:Arial;"> </span><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">TechWomen</span></a><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"> program. From their website: </span></div>
<blockquote><div><strong style="font-size:medium;font-family:Times New Roman;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><em>TechWomen brings emerging women leaders in Science, Technology, Engineering and Mathematics &nbsp;from the Middle East and Africa together with their counterparts in the United States for a professional mentorship and exchange program. TechWomen connects and supports the next generation of women entrepreneurs in these fields by providing them access and opportunity to advance their careers and pursue their dreams.</em></span></strong></div>
<div><span style="font-size:small;"><span style="background-color:transparent;vertical-align:baseline;"><span style="font-family:Arial;"><em><a href="http://www.techwomen.org/" target="_blank">http://www.techwomen.org/ </a></em></span></span></span></div>
</blockquote>
<div><strong style="font-size:medium;font-family:Times New Roman;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><em>&nbsp;</em>As soon as I read that, I applied right away. &nbsp;This was exactly the type of program I was looking for to help share what I&#8217;ve learned.</span></strong></div>
<p />
<div>
<div style="text-align:center;"><strong style="font-size:medium;font-family:Times New Roman;font-weight:normal;"><img src="https://lh6.googleusercontent.com/gcKqF2SiXwN3U3gCGM1jFJxbo28ES_9w2gMyBQXJZNZfWt9fvjR3oHxNXHXPkSeYIAa4RYnFRas99FUF6Ib2R9hkSdr0E8qagK0-FBTODEGhyMIlmO8" height="227px;" alt="" width="425px;" /></strong></div>
</div>
<div><strong style="font-size:medium;font-weight:normal;"> <span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">&nbsp;</span><br /><span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;">It must have been written in the stars as I was accepted as a mentor in the program. &nbsp;I was matched with </span><a href="http://www.linkedin.com/profile/view?id=25153291&amp;locale=en_US&amp;trk=tyah" target="_blank"><span style="font-family:arial, helvetica, sans-serif;">Heba Hosny</span></a><span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;"> who is an emerging leader from Egypt. &nbsp;She works as a QA Engineer at a </span><a href="http://www.vimov.com/" target="_blank" style="font-family:Times New Roman;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">Vimov</span></a><span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;">, an Alexandria based mobile application company. During her three week internship at Flurry she was involved in the process of testing the full suite of Flurry products.</span>
<p /> <span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;">During Heba&rsquo;s stay with us she was like a sponge, soaking up the knowledge to learn what it takes to build and run a fast-paced, successful company in Silicon Valley. In her own words,</span></strong></div>
<p />
<div><span style="font-size:medium;font-weight:normal;"><span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;"></span></span>
<div>
<blockquote><span style="font-family:Arial;"><span style="font-size:15px;">&ldquo;EVERYBODY likes to go behind the scenes. Getting backstage access to how Flurry manages their analytics business was an eye opening experience for me. I was always curious to see how Flurry makes this analytics empire, being behind the curtains with them for just a month has been very inspiring for me to the extent that some of what Flurry does has became pillars of how I daily work as a tester for Flurry analytics product used by the company I work for.</span></span></p></blockquote>
</div>
<div>
<blockquote><span style="font-family:Arial;"><span style="font-size:15px;">In a typical Internship, you join one company and at the end of the day you find yourself sitting in the corner with no new valuable information. You have no ability to even contact a senior guy to have a chat with him. Well, my internship at Flurry was the total OPPOSITE of that.</span></span></p></blockquote>
</div>
<div>
<blockquote><span style="font-family:Arial;"><span style="font-size:15px;">The Flurry workplace is different. In Flurry managers, even C levels, are sitting alongside engineering, business development, marketing, sales, etc. This open environment allowed me to meet with company CEO, CTO, managers, and even sitting next to the analytics manager.</span></span></p></blockquote>
<blockquote><p><span style="font-family:Arial;"><span style="font-size:15px;">&nbsp;</span></span><span style="font-size:15px;font-family:Arial;background-color:transparent;">In short, an internship at Flurry for me was like a company wide in-depth journey of how you can run a superb analytics shop and what it&#8217;s like to deal with HUGE amounts of data like what Flurry works with .&rdquo;</span></p></blockquote>
</div>
<p><span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;">Working with Heba during her internship was a great experience. The experience of hosting an emerging leader was very fruitful. In QA we were able to implement some of the new tools Heba introduced to us, such as the test case management tool </span><span style="font-family:arial, helvetica, sans-serif;"><a href="http://www.testiatarantula.com/" target="_blank">Tarantula</a><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">. Heba also gave us the opportunity to learn more about her culture </span></span><span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;">and gave members of our staff a chance to practice their Arabic. The San Francisco Bay Area is a very diverse place but this is the first chance many of us have gotten to hear a first hand account of the Arab Spring.</span>
<p /> <span style="font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;">From our experience in the tech field, it&#8217;s obvious that the industry suffers from a noticeable lack of strong female leadership at the &nbsp;top. It&rsquo;s time that women who value both a rich home life and a fulfilling career explore the tech startup world. Participating in programs such as TechWomen will help in this regard. These programs benefit not only the mentee and mentor, but the industry as a whole. Mentees who gain experience in Silicon Valley tech companies will pay it forward to next generations of future tech women in their communities by sharing their experiences. Mentors in the program not only learn from their mentees but are able to create a sense of community to help make sure the mentee has a successful internship. Company-wise, participating in programs like TechWomen bring tremendous exposure to Flurry outside of the mobile community. As we enrich more women&#8217;s lives in the tech field, we can share even more experiences to help inspire young women and girls to know it&#8217;s possible to touch the Silicon Valley dream, no matter where in the world they are.</span></div>
<p />
<div><strong style="font-size:medium;font-family:Times New Roman;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;">For more information:</span></strong></div>
<p />
<div><span style="font-family:Arial;"><span style="font-size:15px;"><a href="http://www.techwomen.org/">http://www.techwomen.org/</a></span></span></div>
<p />
<div><span style="font-family:Arial;"><span style="font-size:15px;"><a href="http://www.vimov.com/">http://www.vimov.com/</a></span></span></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/174414955/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/174414955/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=174414955&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=lLZYv6_ZPVU:gfn598MEGdE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=lLZYv6_ZPVU:gfn598MEGdE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/lLZYv6_ZPVU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2013/01/22/tech-women/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>

		<media:content url="https://lh6.googleusercontent.com/kUMkblIbulk6WnaTKXo_sEEO4_XEIw4YbAGRJnjAgGOEMvq9k4NdAJkt8nWjXsx_2tW4Sz8MVYF0sP_X_NiZ4pM8ODdmLM3nnuBhg6ul6yN-cz1McHY" medium="image" />

		<media:content url="https://lh6.googleusercontent.com/gcKqF2SiXwN3U3gCGM1jFJxbo28ES_9w2gMyBQXJZNZfWt9fvjR3oHxNXHXPkSeYIAa4RYnFRas99FUF6Ib2R9hkSdr0E8qagK0-FBTODEGhyMIlmO8" medium="image" />
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2013/01/22/tech-women/</feedburner:origLink></item>
		<item>
		<title>The Benefits of Good Cabling Practices</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/qCbHPvFupZc/</link>
		<comments>http://flurrytechblog.wordpress.com/2012/12/20/the-benefits-of-good-cabling-practices-28386/#comments</comments>
		<pubDate>Thu, 20 Dec 2012 02:48:00 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/the-benefits-of-good-cabling-practices-28386</guid>
		<description><![CDATA[An organized rack makes a world of difference in tracing and replacing cables, easily removing hardware, and most importantly increasing airflow. By adopting good cabling habits, your hardware will run cooler and more efficiently and ensure the he...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=172641113&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p class="p1"><span style="font-size:small;">An organized rack makes a world of difference in tracing and replacing cables, easily removing hardware, and most importantly increasing airflow. By adopting good cabling habits, your hardware will run cooler and more efficiently and ensure the health and longevity of your cables. You also prevent premature hardware failures caused by heat retention. Good cabling practices don&#8217;t sound important but it does make a difference. It&#8217;s also nice to look at or show off to your friends/enemies.</span></p>
<p class="p1"><span style="font-size:small;">When cabling, here are some practices Flurry lives by:</span></p>
<p class="p1"><span style="font-size:small;"><strong>Label everything</strong></span></p>
<p class="p1"><span style="font-size:small;">There has never been a situation where you&#8217;ve heard someone say, &#8220;I wish I hadn&#8217;t labeled this.&#8221; Labeling just makes sense. Spend the extra time to label both ends of the network and power cables. Your sanity will thank you. If you&#8217;re really prepared, print out the labels on a sheet ahead of time so they&#8217;ll be ready to use.</span></p>
<p class="p1"><span style="font-size:small;"><strong>Cable length</strong></span></p>
<p class="p1"><span style="font-size:small;">When selecting cable length, there are two schools of thought. There are those who want exact lengths and those who prefer a little extra slack. The majority of messy cabling jobs are from selecting improper cable lengths so use shorter cables where possible. A good option is custom made cables. You get the length that you need without any excess.&nbsp;This option is usually expensive in either time or money.&nbsp;The other option is to purchase standard length cables. Assuming that you have a 42U rack, the furthest distance between two network ports is a little over six feet. In our rack build outs, we&#8217;ve had great results using standard five foot network cables for our server to switch connections.&nbsp;</span></p>
<p class="p1"><span style="font-size:small;"><strong>Cable management arms</strong></span></p>
<p class="p1"><span style="font-size:small;">When purchasing servers, some manufacturers provide a cable management arm with your purchase. They allow you to pull out your server without unplugging any cables. For this added benefit, they provide bulk, retain heat, and reduce proper airflow. If you have them, we suggest that you don&#8217;t use them. Under most circumstances, you would unplug all cables before you pull out a server anyway.</span></p>
<p class="p1"><span style="font-size:small;"><strong>No sharp bends</strong></span></p>
<p class="p1"><span style="font-size:small;">Cables do require a bit of care when being handled. A cable&#8217;s integrity can suffer with any sharp bends so try to avoid this. In the past, we have seen port speed negotiation and intermittent network issues cause by damaged network cables.</span></p>
<p class="p1"><span style="font-size:small;"><strong>Use mount points</strong></span></p>
<p class="p1"><span style="font-size:small;">As you group cables together, utilize anchor points inside of the rack to minimize stress on cable ends. Prolonged stress on the cable ends can cause the cable and socket it&#8217;s connected in to break. Power ends are also known to unplug. The weight of the bundled power cables can gradually&nbsp;unplug it at any moment.&nbsp;Using anchor points will help alleviate directed stress to the outlet.</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1935_3-scaled1000.jpg"><img alt="Img_1935_3" height="249" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1935_3-scaled1000.jpg?w=500&#038;h=249" width="500" /></a></div>
<p></span></p>
<p class="p1">&nbsp;</p>
<p class="p1"><span style="font-size:small;"><strong>Less sharing</strong></span></p>
<p class="p1"><span style="font-size:small;">Isolate different types of cables (power, network, kvm, etc) into different runs. Separating cable types will allow for easy access and changes. Bundled power cables can cause electromagnetic interference on surrounding cables so it would be wise to separate power from network cables. If you must keep copper network and power cables close together, try to keep them at right angles. Standing at the back of the rack, network cables are positioned on the left hand side of the rack while power cables are generally on the right in our setup.</span></p>
<p class="p1"><span style="font-size:small;"><strong>Lots and lots of velcro</strong></span></p>
<p class="p1"><span style="font-size:small;">We&#8217;ve seen the benefits of velcro cable ties very early on. It&#8217;s got a lot of favorable qualities that plastic zip ties do not. They&#8217;re easy to add/remove and also retie. They&#8217;re also great when mounting bundled cables into anchor points inside of the racks. If your velcro ties come with a slotted end, do not give into the urge to thread the velcro into the ends. It&#8217;s annoying to unwrap and rethread.&nbsp;Don&#8217;t be shy to cut the velcro to length, either; using just the right length of velcro can make it easier to bundle and re-bundle cables.&nbsp;</span></p>
<p class="p1"><span style="font-size:small;">Now that you have these tips in mind, let&#8217;s get started on cabling a Flurry rack.</span></p>
<p class="p1"><span style="font-size:small;">1. Facing the back of a 42U rack, add a 48 port switch in about the middle of the rack (position 21U (21st from the bottom). Once you have all your servers racked, now the fun part being, cabling. Let&#8217;s start with the network.</span></p>
<p class="p1"><span style="font-size:small;">&nbsp;2. From the top most server, connect the network cable to the top left port of your switch, which should be port 1.</span></p>
<p class="p1"><span style="font-size:small;">3. As you go down the rack, connect the network cables on the top row of ports from left to right on the switch (usually odd numbered ports). Stop when you&#8217;ve reached the switch.</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1933_3-scaled1000.jpg"><img alt="Img_1933_3" height="376" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1933_3-scaled1000.jpg?w=500&#038;h=376" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">4. Using the velcro cable ties, gather together the cables in a group of ten and bundle the cabled groups with the cable ties. Keep the bundle on the left hand side of the rack. You will have one group of ten and one group of eleven that form into one bundled cable.</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1932_3-scaled1000.jpg"><img alt="Img_1932_3" height="783" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1932_3-scaled1000.jpg?w=500&#038;h=783" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">5. For the bottom set of servers, start with the lowest server (rack position 1U) and connect the network cable to the bottom left most port on the switch.</span></p>
<p class="p1"><span style="font-size:small;">6. Starting from the bottom up, connect the network cables on the bottom row of ports from left to right on the switch (usually even numbered ports).</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1940_3-scaled1000.jpg"><img alt="Img_1940_3" height="243" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1940_3-scaled1000.jpg?w=500&#038;h=243" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">7. Doing the same as the top half of the rack, gather together the cables in a group of ten and bundle the cabled groups with the cable ties. Keep these bundles on the left hand side of the rack. You&#8217;ll end up with two bundles of ten that form into one bundled cable. Look pretty decent?</span></p>
<p class="p1"><span style="font-size:small;">8. Now, lets get to power cabling. In this scenario, we will have three power distribution units (pdus), one on the left and two on the right side of the rack. Starting from the top of the rack, velcro together five power cables and plug them into one of the pdu strips on the left side of the rack from the top down.</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1930_3-scaled1000.jpg"><img alt="Img_1930_3" height="573" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1930_3-scaled1000.jpg?w=500&#038;h=573" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">9. Take another two sets of four bundled power cables and plug them into the other pdu strips on the right hand side also following the top to bottom convention. You should end up with a balanced distribution of power plugs.</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1931_4-scaled1000.jpg"><img alt="Img_1931_4" height="843" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1931_4-scaled1000.jpg?w=500&#038;h=843" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">10. Take a bundle of six power cables and plug them into the pdu strip on the left hand side.</span></p>
<p class="p1"><span style="font-size:small;">11. Take another two sets of four power cables and plug them into the two pdu strips on the right hand side.</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1936_3-scaled1000.jpg"><img alt="Img_1936_3" height="811" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1936_3-scaled1000.jpg?w=500&#038;h=811" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">12. Start from the bottom up, bundle the power cables in groups of five. You will end up with two sets of five power cables and a bundle of four.</span></p>
<p class="p1"><span style="font-size:small;">13. Plug the bundle of four power cables into the pdu on the left hand side.</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1939_3-scaled1000.jpg"><img alt="Img_1939_3" height="707" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1939_3-scaled1000.jpg?w=500&#038;h=707" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">At this point, you can take a step back and admire your work. Hopefully, it looks sort of like this:</span></p>
<p class="p1"><span style="font-size:small;">
<div class='p_embed p_image_embed'><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1942_43-scaled1000.jpg"><img alt="Img_1942_43" height="871" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1942_43-scaled1000.jpg?w=500&#038;h=871" width="500" /></a><a href="http://flurrytechblog.files.wordpress.com/2012/12/img_1942_52-scaled1000.jpg"><img alt="Img_1942_52" height="751" src="http://flurrytechblog.files.wordpress.com/2012/12/img_1942_52-scaled1000.jpg?w=500&#038;h=751" width="500" /></a></div>
<p></span></p>
<p class="p1"><span style="font-size:small;">Good cabling can be an art form. As in any artistic endeavor, it takes a lot of time, patience, skill, and some imagination. There is no one size fits all solution, but hopefully this post will provide you with some great ideas on your next rack build out.</span></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/172641113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/172641113/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=172641113&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=qCbHPvFupZc:2Qc1sYAFWAw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=qCbHPvFupZc:2Qc1sYAFWAw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/qCbHPvFupZc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2012/12/20/the-benefits-of-good-cabling-practices-28386/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1935_3-scaled1000.jpg?w=300" medium="image">
			<media:title type="html">Img_1935_3</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1933_3-scaled1000.jpg?w=300" medium="image">
			<media:title type="html">Img_1933_3</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1932_3-scaled1000.jpg?w=191" medium="image">
			<media:title type="html">Img_1932_3</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1940_3-scaled1000.jpg?w=300" medium="image">
			<media:title type="html">Img_1940_3</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1930_3-scaled1000.jpg?w=261" medium="image">
			<media:title type="html">Img_1930_3</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1931_4-scaled1000.jpg?w=177" medium="image">
			<media:title type="html">Img_1931_4</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1936_3-scaled1000.jpg?w=185" medium="image">
			<media:title type="html">Img_1936_3</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1939_3-scaled1000.jpg?w=212" medium="image">
			<media:title type="html">Img_1939_3</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1942_43-scaled1000.jpg?w=172" medium="image">
			<media:title type="html">Img_1942_43</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/12/img_1942_52-scaled1000.jpg?w=199" medium="image">
			<media:title type="html">Img_1942_52</media:title>
		</media:content>
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2012/12/20/the-benefits-of-good-cabling-practices-28386/</feedburner:origLink></item>
		<item>
		<title>Exploring Dynamic Loading of Custom Filters in HBase</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/zi4gWa8AYBA/</link>
		<comments>http://flurrytechblog.wordpress.com/2012/12/06/exploring-dynamic-loading-of-custom-filters-i/#comments</comments>
		<pubDate>Thu, 06 Dec 2012 20:07:14 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/exploring-dynamic-loading-of-custom-filters-i</guid>
		<description><![CDATA[Any program that pulls data from a large HBase table containing terabytes of data spread over many nodes will need to put a bit of thought into the retrieval of this data. Failure to do this may mean waiting for and subsequently processing a lot o...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=171005186&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p style="text-align:left;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Any program that pulls data from a large HBase table containing terabytes of data spread over many nodes will need to put a bit of thought into the retrieval of this data. Failure to do this may mean waiting for and subsequently processing a lot of unnecessary data, to the point where it renders this program (whether a single-threaded client or a MapReduce job) useless. HBase&rsquo;s Scan API helps in this aspect. It configures the parameters of the data retrieval, including the columns to include, start and stop rows and batch sizing. </span><br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">&nbsp;</span><br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">The Scan can also include a filter which can be the most impactful</span></strong><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;"> way to improve performance of scans of an HBase table. This filter is applied to a table and screens out unwanted rows from being included in a result set. A well-designed filter is performant and minimizes the data scanned and returned to the client. There are many useful Filters that come standard with Hbase, but sometimes the best solution is to use a custom Filter tuned to your HTable&#8217;s schema.</span></strong></p>
<p style="text-align:left;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Before your custom filter can be used, it will have to compiled, packaged in a jar, and deployed to all the regionservers. Restarting the HBase cluster is necessary for the regionservers to pick up the code in their classpaths. Therein lies the problem &ndash; an HBase restart takes a non-trivial amount of time (although rolling restarts mitigate that somewhat) and the downtime is significant with a cluster as big as Flurry&#8217;s.</span>
<p /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">This is where dynamic filters come in. The word &#8216;dynamic&#8217; refers to the on-demand loading of these custom filters, just like loading external modules at runtime in a typical application server or web server. In this post, we will explore an approach that makes this possible in the cluster.</span>
<p /><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">How It Works Now</span><br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Before we dive into the workings of dynamically loading filters, let&#8217;s see how regular custom filters work.</span>
<p /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Assuming the custom filter has already been deployed to a jar in the regionservers&rsquo; </span></strong><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">classpath, the client can simply use the filter, e.g. in a full table scan, like this</span></strong></p>
<p style="text-align:left;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="font-size:small;">
<p><a href="https://gist.github.com/4227003">https://gist.github.com/4227003</a></p>
<p></span></span></strong></p>
<p style="text-align:left;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">This filter will have to be pushed to the regionservers to be run server-side. The sequence of how the custom filter gets replicated on the regionservers is as follows:</span><span style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><span> </span></span></strong></p>
<ol style="margin-top:0;margin-bottom:0;text-align:left;">
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><span style="font-size:small;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-family:Arial;background-color:transparent;vertical-align:baseline;">The client serializes the Filter class name and its state into a byte stream by calling the CustomFilter&#8217;s write(DataOutput) method.</span></strong></span></li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><span style="font-size:small;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-family:Arial;background-color:transparent;vertical-align:baseline;">The client directs the byte array to the regionservers that will be part of the scan.</span></strong></span></li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><span style="font-size:small;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-family:Arial;background-color:transparent;vertical-align:baseline;">Server-side, the RegionScanner re-creates the Scan, including the filter, using the byte stream. Part of the stream is the filter&rsquo;s class name, and the default classloader uses this fully qualified name to load the class using Class.forName(). </span></strong></span></li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><span style="font-size:small;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-family:Arial;background-color:transparent;vertical-align:baseline;">The filter is then instantiated using its empty constructor and configured using the rest of the filter byte array (using the filter&#8217;s readFields(DataInput) method (see org.apache.hadoop.hbase.client.Scan for details).</span></strong></span></li>
<li style="font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;"><span style="font-size:small;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-family:Arial;background-color:transparent;vertical-align:baseline;">The filter is then applied as a predicate on each row.</span></strong></span></li>
</ol>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><img src="https://lh4.googleusercontent.com/nXix2UhZLMyUp8dh68jNI3lTq20Zulg7KP0wqhvfMWarriJ8sJPydSa42RjOm42XHscpfabRkbZDbLJ3lM5_un38ArDY_N6ZsHqkcC2UnvcRQqiGtGo" height="353px;" alt="" style="display:block;margin-left:auto;margin-right:auto;" width="524px;" /></strong></p>
<p><span style="font-size:x-small;">(1) myfilter.jar containing our custom filter resides locally in the regionservers&#8217; classpath</span><br /><span style="font-size:x-small;">(2) the custom filter is instantiated using the default Classloader</span></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Once deployed, this definition of our custom filter is static. We can make an ad hoc query using the combination of filters, but if we need to add, extend or replace a custom filter, it has to be added to the regionserver&rsquo;s classpath and we have to wait for its next restart before those filters can be used. </span>
<p /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">There is a faster way. </span>
<p /><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Dynamic Loading</span><br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">A key takeaway from the previous section is that Filters are Writables &ndash; they are instantiated using the name of the class and then configured by a stream of bytes that the Filter understands. This makes the filter configuration highly customizable and we can use this flexibility to our advantage.</span>
<p /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Rather than create a regular Filter, we introduce a ProxyFilter which acts as the extension point through which we can load our custom Filters on demand. During runtime, it will load the custom class filter itself. </span>
<p /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Let&rsquo;s look at some </span><a href="https://github.com/vallancelee/hbase-filter/tree/master/customFilters"><span style="font-size:15px;color:#1155cc;background-color:transparent;vertical-align:baseline;">example code</span></a><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">. To start with, there is just a small change we have to make on the client; the ProxyFilter now wraps the Filter or FilterList we want to use in our scan.</span><br /></strong></p>
<p><span style="font-size:small;">
<p><a href="https://gist.github.com/4227336">https://gist.github.com/4227336</a></p>
<p></span></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">The ProxyFilter passes its own class name to be instantiated on the server side, and serializes the custom filter after.</span></strong></p>
<p>
<p><a href="https://gist.github.com/4227434">https://gist.github.com/4227434</a></p>
</p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">On the regionserver the ProxyFilter is initialized in the same way as described in the previous section. The byte stream that follows should minimally contain the filter name and its configuration byte array. In the ProxyFilter&#8217;s readFields method, the relevant code looks like this.</span></strong></strong></strong></strong></p>
<p>
<p><a href="https://gist.github.com/4227524">https://gist.github.com/4227524</a></p>
</p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">This is very much like how the default Scan re-creates the Filter on the regionserver with one critical difference &ndash; it uses a filterModule object to obtain the Class definition of the custom filter.</span><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;"> </span><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">This module retrieves the custom filter Class and returns it to ProxyFilter for instantiation and configuration. </span>
<p /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">There can be different strategies for retrieving the custom filter class. Our example code copies the jar file from the Hadoop filesystem to a local directory and delegates the loading of the Filter classes from this jar to a custom classloader [3]. </span>
<p /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">To configure the location of the directory the module searches for the filters.jar in HDFS, add the following property in hbase-site.xml.</span>
<p /><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&lt;</span><span style="font-size:13px;font-family:Consolas;color:#3f7f7f;background-color:transparent;vertical-align:baseline;">property</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&gt;</span><br /><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&lt;</span><span style="font-size:13px;font-family:Consolas;color:#3f7f7f;background-color:transparent;vertical-align:baseline;">name</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&gt;</span><span style="font-size:13px;font-family:Consolas;background-color:transparent;vertical-align:baseline;">flurry.hdfs.filter.jar</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&lt;/</span><span style="font-size:13px;font-family:Consolas;color:#3f7f7f;background-color:transparent;vertical-align:baseline;">name</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&gt;</span><br /><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&lt;</span><span style="font-size:13px;font-family:Consolas;color:#3f7f7f;background-color:transparent;vertical-align:baseline;">value</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&gt;</span><span style="font-size:13px;font-family:Consolas;background-color:transparent;vertical-align:baseline;">/flurry/filters.jar</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&lt;/</span><span style="font-size:13px;font-family:Consolas;color:#3f7f7f;background-color:transparent;vertical-align:baseline;">value</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&gt;</span><br /><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&lt;/</span><span style="font-size:13px;font-family:Consolas;color:#3f7f7f;background-color:transparent;vertical-align:baseline;">property</span><span style="font-size:13px;font-family:Consolas;color:#008080;background-color:transparent;vertical-align:baseline;">&gt;</span><br /><img src="https://lh4.googleusercontent.com/iwXI3jjb_Op0OaSEd6cjayru4rRXLFroM2qaRR3_UMZnJnFB_xXYhZVjhwwJLPH_7mxOreRzQ-do5j_eZjHI27TXOpBP-7017qVLC8MatLk23foEOjQ" height="432px;" alt="" style="float:left;" width="633px;" /><span style="background-color:transparent;font-size:x-small;">(1) The custom filter jar resides in a predefined directory in HDFS</span></strong><br /><span style="font-size:x-small;font-family:Arial;">(2) The proxyfilter.jar containing the extension point needs to reside locally in the regionserver&#8217;s classpath</span><br /><span style="font-size:x-small;"><span style="font-family:Arial;">(3)&nbsp;</span><span style="font-family:Arial;">The ProxyFilter is instantiated using the default ClassLoader</span></span><br /><span style="font-size:x-small;"><span style="font-family:Arial;">(4) If necessary, the rowfilter.jar is downloaded from a preset Path in HDFS. A custom classloader in ProxyFilter proceeds to instantiate the correct filter. Filter interface calls are then delegated to the enclosed filter.</span></span></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">With the ProxyFilter in place, it is now simply a matter of placing or replacing the jar in the Hadoop FS directory to pick up the latest filters. </span></strong></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Reloading Filters</span><br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">When a new Scan is requested on the server side, this module first checks up on the filter.jar. If this jar is unchanged, the previously loaded Classes are returned. However, if the jar has been updated, the module repeats the process of downloading it from HDFS, creating a new instance of the classloader and reloading the classes from this modified jar. The previous classloader is dereferenced and left to be garbage collected. Restarting the HBase cluster is not required.</span></strong></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"> </strong></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><img src="https://lh5.googleusercontent.com/TtcYQF9WoC--NeX40OkPnE65wNOAC0MBEx4Sz0Q3hjVyyD7ybht8rYIyD7vaTQBlns9w4WBJtDDRGqKt9Mvw_bH73CwjVKcg9qeoa0s0AboQwx2OsyE" height="262px;" alt="" style="display:block;margin-left:auto;margin-right:auto;" width="447px;" /></strong></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"> </strong></p>
<p style="text-align:center;margin-top:0;margin-bottom:0;"><span style="font-size:x-small;">The HdfsJarModule keeps track of the latest custom filter definitions using a separate classloader for the different jar versions</span></p>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Custom classloading and reloading can be a class-linking, ClassCastException minefield, but the risk here is mitigated by the highly specialized use case of Filtering. The filter is instantiated and configured per scan and its object lifecycle limited to the time it takes to do the scan in the regionserver. The example uses the child-first classloader mentioned in a previous </span><a href="http://tech.flurry.com/using-the-java-classloader-to-write-efficient"><span style="font-size:15px;color:#1155cc;background-color:transparent;vertical-align:baseline;">post on ClassLoaders</span></a><span style="font-size:15px;background-color:transparent;vertical-align:baseline;"> that searches for a configured set of URLs before delegating to its parent classloader [2].</span>
<p /><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Things to watch out for</span><span style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span> </span></span><br /> </strong></p>
<ul style="margin-top:0;margin-bottom:0;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"> </strong>
<li style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="background-color:transparent;vertical-align:baseline;">The example code has a performance overhead as it makes additional calls to HDFS to check for the modification time of the filter jar when a filter is first instantiated. This may be a significant factor for smaller scans. If so, the logic can be changed to check the jar less frequently.</span></li>
<li style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="background-color:transparent;vertical-align:baseline;">The code is also very na&iuml;ve at this point. Updating the filter.jar in the Hadoop FS while a table scan is happening can have undesired results if the updated filters are not backward compatible. Different versions of the jar can be picked up by the RegionServers for the same scan as they check and instantiate the Filters at different times.</span></li>
<li style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="background-color:transparent;vertical-align:baseline;">Mutable static variables are discouraged in the custom Filter because they will be reinitialized when the class is reloaded dynamically.</span></li>
</ul>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"><span style="font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Extensions</span><br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">The example code is just a starting point for more interesting functionality tailored to different use cases. Scans using filters can also be used in MapReduce jobs and coprocessers. A short list of possible ways to extend the code:</span><br /> </strong></p>
<ul style="margin-top:0;margin-bottom:0;"><strong style="font-family:Arial;font-size:medium;font-weight:normal;"> </strong>
<li style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="background-color:transparent;vertical-align:baseline;">The most obvious weakness in the example implementation is the ProxyFilter only supports one jar. Extending that to include all jars in a filter directory will be a good start. [4]<span> </span></span></li>
<li style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="background-color:transparent;vertical-align:baseline;">Different clients may expect certain versions of Filters. Some versioning and bookkeeping logic will be necessary to ensure that the ProxyFilter can serve up the correct filter to each client.<span> </span></span></li>
<li style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="background-color:transparent;vertical-align:baseline;">Generalize the solution to include MapReduce scenarios that use HBase as the input source. The module can load the custom filters at the start of each map task from the MR job library instead, unloading the filters after the task ends.</span></li>
<li style="font-size:15px;background-color:transparent;vertical-align:baseline;"><span style="background-color:transparent;vertical-align:baseline;">Support other JVM languages for filtering. We have tried serializing Groovy 1.6 scripts as Filters but performance was several times slower.</span></li>
</ul>
<p><strong style="font-family:Arial;font-size:medium;font-weight:normal;"> <br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;">Using the Proxyfilter as a generic extension point for custom filters allows us to improve our performance without the hit of restarting our entire HBase cluster.</span>
<p /><span style="font-size:small;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;">Footnotes</span><br /><span style="font-size:x-small;background-color:transparent;vertical-align:baseline;">[1] Class Reloading Basics</span><span style="background-color:transparent;vertical-align:baseline;"> </span><span style="font-size:x-small;"><a href="http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html"><span style="color:#1155cc;background-color:transparent;vertical-align:baseline;">http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html</span></a></span><br /><span style="font-size:x-small;background-color:transparent;vertical-align:baseline;">[2] See our blog post on ClassLoaders for alternate classloader delegation</span><span style="background-color:transparent;vertical-align:baseline;"> </span><span style="font-size:x-small;"><a href="http://tech.flurry.com/using-the-java-classloader-to-write-efficient"><span style="color:#1155cc;background-color:transparent;vertical-align:baseline;">http://tech.flurry.com/using-the-java-classloader-to-write-efficient</span></a><span style="background-color:transparent;vertical-align:baseline;"><span> </span></span></span><br /><span style="font-size:x-small;background-color:transparent;vertical-align:baseline;">[3] The classloader in our example resembles the one described in this ticket </span><span style="font-size:x-small;"><a href="https://issues.apache.org/jira/browse/HBASE-1936"><span style="color:#1155cc;background-color:transparent;vertical-align:baseline;">https://issues.apache.org/jira/browse/HBASE-1936</span></a></span><br /><span style="font-size:x-small;background-color:transparent;vertical-align:baseline;">[4] A new classloader has been just been introduced in hbase-0.92.2 for coprocessors, and it seems to fit perfectly for our dynamic filters</span><span style="background-color:transparent;vertical-align:baseline;"><span style="font-size:small;"> </span></span><span style="font-size:x-small;"><a href="https://issues.apache.org/jira/browse/HBASE-6308"><span style="color:#1155cc;background-color:transparent;vertical-align:baseline;">https://issues.apache.org/jira/browse/HBASE-6308</span></a></span><br /><span style="font-size:x-small;background-color:transparent;vertical-align:baseline;">[5] Example code</span><span style="background-color:transparent;vertical-align:baseline;"> </span><span style="font-size:x-small;"><a href="https://github.com/vallancelee/hbase-filter/tree/master/customFilters"><span style="color:#1155cc;background-color:transparent;vertical-align:baseline;">https://github.com/vallancelee/hbase-filter/tree/master/customFilters</span></a></span><br /><span style="font-size:15px;background-color:transparent;vertical-align:baseline;"> </span></strong></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/171005186/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/171005186/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=171005186&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=zi4gWa8AYBA:xV9HaxFPdLk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=zi4gWa8AYBA:xV9HaxFPdLk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/zi4gWa8AYBA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2012/12/06/exploring-dynamic-loading-of-custom-filters-i/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>

		<media:content url="https://lh4.googleusercontent.com/nXix2UhZLMyUp8dh68jNI3lTq20Zulg7KP0wqhvfMWarriJ8sJPydSa42RjOm42XHscpfabRkbZDbLJ3lM5_un38ArDY_N6ZsHqkcC2UnvcRQqiGtGo" medium="image" />

		<media:content url="https://lh4.googleusercontent.com/iwXI3jjb_Op0OaSEd6cjayru4rRXLFroM2qaRR3_UMZnJnFB_xXYhZVjhwwJLPH_7mxOreRzQ-do5j_eZjHI27TXOpBP-7017qVLC8MatLk23foEOjQ" medium="image" />

		<media:content url="https://lh5.googleusercontent.com/TtcYQF9WoC--NeX40OkPnE65wNOAC0MBEx4Sz0Q3hjVyyD7ybht8rYIyD7vaTQBlns9w4WBJtDDRGqKt9Mvw_bH73CwjVKcg9qeoa0s0AboQwx2OsyE" medium="image" />
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2012/12/06/exploring-dynamic-loading-of-custom-filters-i/</feedburner:origLink></item>
		<item>
		<title>Squashing bugs in multithreaded Android code with CheckThread</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/omlozI2gswE/</link>
		<comments>http://flurrytechblog.wordpress.com/2012/11/19/squashing-bugs-in-multithreaded-android-code/#comments</comments>
		<pubDate>Mon, 19 Nov 2012 22:14:47 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/squashing-bugs-in-multithreaded-android-code</guid>
		<description><![CDATA[Writing correct multithreaded code is difficult, and writing Android apps is no exception. Like many mobile platforms, Android's UI framework is single threaded and requires the application developer to manage threads with no thread-safe guarantee...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=169126789&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Writing correct multithreaded code is difficult, and writing Android apps is no exception. Like many mobile platforms, Android&#8217;s UI framework is single threaded and requires the application developer to manage threads with no thread-safe guarantee. If your app is more complicated than &#8220;Hello, World!&#8221; you can&#8217;t escape writing multithreaded code. For example, to build a smooth and responsive UI, you will have to move long running operations like network and disk IO to background threads and then return to the UI thread to update the UI.</p>
<p>Thankfully, Android provides some tools to make this easier such as the AsyncTask utility class and the StrictMode API. You can also use good software development practices such as adhering to strict code style and requiring careful code review of code that involve the UI thread. Unfortunately, these approaches require diligence, are prone to human error, or only catch errors at runtime.</p>
<p><strong>CheckThread for Android</strong></p>
<p><a href="http://www.checkthread.org/">CheckThread</a> is an open source project authored by Joe Conti that provides annotations and a simple static analysis tool for verifying certain contracts in multithreaded programs. It&#8217;s not a brand new project and it&#8217;s not very difficult to use, but it hasn&#8217;t had a very high adoption for Android apps. It offers an automated alternative to exclusively using comments and code review to ensuring no bugs related to the UI thread are introduced in your code.&nbsp;The annotations provided by CheckThread are:&nbsp;@ThreadSafe,&nbsp;@NotThreadSafe,&nbsp;@ThreadConfined</p>
<p>ThreadSafe and NotThreadSafe are described in Java Concurrency in Practice, and CheckThread enforces the same semantics that book defines. For the purposes of this blog post, the only annotation that we&#8217;ll be using is ThreadConfined.</p>
<p>Thread confinement is a general property of restricting data or code to access from only a single thread. A data structure confined to the stack is inherently thread confined. A method that is only ever called by a single thread is also thread confined. In Android, updates to the UI must be confined to the UI thread. In very concrete terms, this implies that any method that mutates the state of a View should only be called from the UI thread. If this policy is violated, the Android framework may throw a RuntimeException, but also may simply produce undefined behavior, depending on the specific nature of the update to the UI.</p>
<p>CheckThread supports defining thread policies in XML files, so while it would be possible, it&#8217;s not necessary to download the source of the Android framework code and manually add annotations to it. Instead, we can simply define a general thread policy to apply to Android framework classes.</p>
<p><strong>Time for an Example</strong></p>
<p>The following example demonstrates how to declare a thread policy in XML, annotate a simple program and run the CheckThread analyzer to catch a couple of bugs.</p>
<p>CheckThread&rsquo;s XML syntax supports patterns and wildcards which allows you to concisely define policies for Android framework code. In this example we define two Android specific policies. In general this file would contain more definitions for other Android framework classes and could also contain definitions for your own code.</p>
<p>The first policy declares that all methods in Activity and its subclasses that begin with the prefix &ldquo;on&rdquo; should be confined to the main thread. Since CheckThread has no built-in concept of the Android framework or of the Activity class we need to inform the static analyzer which thread will call these methods.</p>
<p>The second policy declares that all methods in classes ending with &ldquo;View&rdquo; should be confined to the main thread. The intention is to prevent calling any code that modifies that UI from any other thread than the UI thread. This is a little bit conservative since there are some methods in Android View classes that have no side-effects, but it will do for now.</p>
<p>
<p><a href="https://gist.github.com/4113656">https://gist.github.com/4113656</a></p>
</p>
<p>Having defined the thread policy, we can turn to our application code. The example app is the rough beginnings of a Hacker News app. It fetches the RSS feed for the front page, parses the titles and displays them in a LinearLayout.</p>
<p>This first version is naive; it does network IO and XML parsing in Activity.onCreate. This error will definitely be caught by StrictMode, and will likely just crash the app on launch, so it would be caught early in development, but it would be even better if it were caught before the app was even run.</p>
<p>
<p><a href="https://gist.github.com/4113662">https://gist.github.com/4113662</a></p>
</p>
<p>In this code, we make a call to the static method getHttp in the IO utility class. The details of this class and method are not important, but since it does network IO, it should be called from off the UI thread. We&rsquo;ve annotated the entire class as follows:</p>
<p>
<p><a href="https://gist.github.com/4113669">https://gist.github.com/4113669</a></p>
</p>
<p>This annotation tells CheckThread that all the methods in this class should be called from the &ldquo;other&rdquo; thread.</p>
<p>Finally, we&rsquo;re ready to run the static analyzer. CheckThread provides several ways to run the analysis tool, including Eclipse and Intellij plugins, but we&rsquo;ll just use the Ant tasks on the command line. This is what CheckThread outputs after we run the analyzer:</p>
<p>
<p><a href="https://gist.github.com/4113676">https://gist.github.com/4113676</a></p>
</p>
<p>As you can see, CheckThread reports an error: we&rsquo;re calling a method that should be confined to the &ldquo;other&rdquo; thread from a method that&rsquo;s confined to &ldquo;MAIN&rdquo;. One solution to this problem is to start a new thread to do network IO on. We create an anonymous subclass of java.util.Thread and override run, inside of which we fetch the RSS feed, parse it and update the UI.</p>
<p>
<p><a href="https://gist.github.com/4113683">https://gist.github.com/4113683</a></p>
</p>
<p>We&rsquo;ve annotated the run method to be confined to the &ldquo;other&rdquo; thread. CheckThread will use this to validate the call to IO.getHttp. After running the analyzer again, we discover that there&rsquo;s a new error reported:</p>
<p>
<p><a href="https://gist.github.com/4113686">https://gist.github.com/4113686</a></p>
</p>
<p>This time, the error is caused by calling the method setText on a TextView from a different thread than the UI thread. This error is generated by the combination of our thread policy defined in XML and the annotation on the run method.</p>
<p>Instead, we could call the Activity.runOnUiThread with a new Runnable. The Runnable&rsquo;s run method is annotated to be confined to the UI thread, since we&rsquo;re passing it to a framework method that will call it from the UI thread.</p>
<p>
<p><a href="https://gist.github.com/4113689">https://gist.github.com/4113689</a></p>
</p>
<p>Finally, CheckThread reports no errors to us. Of course that doesn&rsquo;t mean that the code is bug free, static analysis of any kind has limits. We&rsquo;ve just gotten some small assurance that the contracts defined in the XML policy and annotations will be held. While this example is simple, and the code we&rsquo;re analyzing would be greatly simplified by using an AsyncTask, it does demonstrate the class of errors that CheckThread is designed to catch. The complete sample project is published on&nbsp;<a href="https://github.com/flurry/checkthread-android-example">Github</a>.</p>
<p><strong>The Pros and Cons of Annotations</strong></p>
<p>One drawback that is probably immediately obvious is the need to add annotations to a lot of your code. Specifically, CheckThread&#8217;s static analysis is relatively simple, and doesn&#8217;t construct a complete call graph of your code. This means that the analyzer will not generate a warning for the code below:</p>
<p>
<p><a href="https://gist.github.com/4113695">https://gist.github.com/4113695</a></p>
</p>
<p>While this may appear to be a significant problem, it&#8217;s my opinion that in practice it is not actually a deal breaker. Java already requires that the programmer write most types in code. This is seen by some as a drawback of Java (and is often cited incorrectly as a drawback of static typing in general). However there are real advantages to annotating code with type signatures, and even proponents of languages with powerful type inference will admit this, since it&#8217;s usually recommended to write the type of &#8220;top-level&#8221; or publicly exported functions even if the compiler can infer the type without any hint.</p>
<p>The annotations that CheckThread uses are similar; they describe an important part of a method&#8217;s contract, that is whether it is thread safe or should be confined to a specific thread. Requiring the programmer to write those annotations elevates the challenge of writing correct multithreaded code to be at the forefront of the programmer&#8217;s mind, requiring that some thought be put into each method&#8217;s contract. The use of automated static analysis makes it less likely that a comment will become stale and describe a method as thread safe when it is not.</p>
<p><strong>The Future of Static Analysis</strong></p>
<p>The good news is that the future of static analysis tools designed to catch multithreaded bugs is looking very bright. A <a href="http://homes.cs.washington.edu/~mernst/pubs/gui-thread-issta-2012.pdf">recent paper</a> published by Sai Zhang, Hao L&uuml;, and Michael D. Ernst at the University of Washington describes a more powerful approach to analyzing multithreaded GUI programs. Their work targets Android applications as well as Java programs written using other GUI frameworks. The analyzer described in their paper specifically does construct a complete call graph of the program being analyzed. In addition, it doesn&#8217;t require any annotations by the programmer and also addresses the use of reflection in building the call graph, which Android specifically uses to inflate layouts from XML. This work was published only this past summer, and the tool itself is underdocumented at the moment, but I recommend that anyone interested in this area read the paper which outlines their work quite clearly.</p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/169126789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/169126789/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=169126789&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=omlozI2gswE:oe_nbEhRiyE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=omlozI2gswE:oe_nbEhRiyE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/omlozI2gswE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2012/11/19/squashing-bugs-in-multithreaded-android-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2012/11/19/squashing-bugs-in-multithreaded-android-code/</feedburner:origLink></item>
		<item>
		<title>Write Once, Compile Twice, Run Anywhere</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/zerw_Ftj8fI/</link>
		<comments>http://flurrytechblog.wordpress.com/2012/11/08/167887291/#comments</comments>
		<pubDate>Thu, 08 Nov 2012 04:32:00 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[java compiler eclipse]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/167887291</guid>
		<description><![CDATA[Many Java developers use a development environment different from the target deployment environment. At Flurry, we have developers running OS X, Windows, and Linux, and everyone is able to contribute without thinking much about the differences of ...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=167887291&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Many Java developers use a development environment different from the target deployment environment.&nbsp; At Flurry, we have developers running OS X, Windows, and Linux, and everyone is able to contribute without thinking much about the differences of their particular operating system, or the fact that the code will be deployed on a different OS.
<p />The secret behind this flexibility is how developed the Java toolchain has become. One tool (<a href="http://www.eclipse.org/" target="_blank">Eclipse</a>)&nbsp; in particular has Eclipsed the rest and become the dominant IDE for Java developers. Eclipse is free, with integrations like JUnit support, and a host of really great plugins making it the de facto standard in Java development, displacing IntelliJ and other options.&nbsp; In fact, entry level developers rarely even think about the compilation step, because Eclipse&#8217;s autocompilation keeps your code compiled every time you save a file.</p>
<p><strong>There&#8217;s Always a Catch</strong></p>
<p>Unfortunately no technology is magical and while this set up rarely causes issues, it can. One interesting case arises when the developer is using the Eclipse 1.6 compiler compliance and the target environment uses Sun&#8217;s 1.6 JDK compiler.&nbsp; For example at Flurry, during development we rely on Eclipse&#8217;s JDT Compiler, but the code we ship gets compiled for deployment on a Jenkins server by Ant using Sun&#8217;s JDK compiler. Note that both the developer and continuous integration environment are building for Java 6, but using different compilers.&nbsp;
<p />Until recently this never came up as an issue as the Eclipse and Sun compilers, even when running on different operating systems, behave <strong>almost</strong> identically.&nbsp; However, we have been running into some interesting (and frustrating) compiler issues that are essentially changing &#8220;Write Once, Run Anywhere&#8221; into &#8220;Write Once, Compile Using Your Target JDK, Run Anywhere.&#8221;&nbsp; We have valid 1.6 Java code using generics, which compiles fine under Eclipse, but won&#8217;t compile using Sun&#8217;s javac.</p>
<p><strong>Let&#8217;s See an Example</strong>
<p />An example of the code in question is below. Note that it meets the Java specification and should be a valid program. In fact, in Eclipse using Java 1.6 compiler compliance the code compiles, but won&#8217;t compile using Sun&#8217;s 1.6 JDK javac.
<p />
<p><a href="https://gist.github.com/4035987">https://gist.github.com/4035987</a></p>
</p>
<p>Compiling this code using javac in the Sun 1.6 JDK gives this compiler error:</p>
<p>
<p><a href="https://gist.github.com/4036089">https://gist.github.com/4036089</a></p>
</p>
<p>&#8220;Write Once, Run Anywhere&#8221; never made any promises about using different compilers, but the fact that our toolchain was using a different compiler than our build server never bore much thought until now.<br /><strong></strong></p>
<p><strong>Possible Solutions</strong></p>
<p>The obvious solution is to have all developers work on the same environment as where the code will be deployed, but this would defer developers from using their preferred environment and impact productivity by constraining our development options. Possible solutions we have kicked around :</p>
<ol>
<li>Have ant compile using the Eclipse incremental compiler, (using flags&nbsp; -Dbuild.compiler=org.eclipse.jdt.core.JDTCompilerAdapter and of course -Dant.build.javac.target=1.6). This side steps the problem by forcing the continuous integration system to use the same compiler as developer laptops, but is not ideal as this was never an intended use of the Eclipse compiler.&nbsp;</li>
<li>Move to the 1.7 JDK for compilation, using a target 1.6 bytecode. This solves this particular issue, but what happens in the future?</li>
<li>Change the code to compile under Sun&#8217;s JDK. This is not a bad option but will cost some speed of development found in the simplicity of Eclipse&#8217;s built in system.&nbsp;</li>
</ol>
<p>My experience has been that Eclipse is a well worn path in the Java world, and its a little surprising that this hasn&#8217;t come up before for us given the heavy use of generics (although there are lots of generics issues which have been logged over at bugs.sun.com, like <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6302954">http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6302954</a> which has come up for us as a related issue &#8211; the &#8220;no unique maximal instance exists&#8221; error message).&nbsp;</p>
<p>Switching to use the Eclipse compiler for our deployable artifacts would be an unorthodox move, and I&#8217;m curious if anyone out there reading this has done that, and if so, with what results.
<p />We had a discussion internally and the consensus was that moving to 1.7 for compilation using a target 1.6 bytecode (#2) should work, but would potentially open us up to bugs in 1.7 (and would require upgrading some internal utility machines to support this).&nbsp; We aren&#8217;t quite ready to make the leap to Java 7, although its probably time to start considering the move.&nbsp;
<p />For now, we coded around the compiler issue, but its coming up for us regularly now, and we are kicking around the ideas on how to resolve.&nbsp; In the near term, for the projects that run into this generics compile issue, developers are back to using good ole ant to check if their code will &#8220;really&#8221; compile.&nbsp; Its easy to forget how convenient autocompilation has become, and the fact that it isn&#8217;t really the same as the build server&#8217;s compiler.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/167887291/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/167887291/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=167887291&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=zerw_Ftj8fI:0ili_oPE6mQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=zerw_Ftj8fI:0ili_oPE6mQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/zerw_Ftj8fI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2012/11/08/167887291/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2012/11/08/167887291/</feedburner:origLink></item>
		<item>
		<title>Regression Testing NodeJS Services with Restify and Mocha</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/5NF2hSdi65A/</link>
		<comments>http://flurrytechblog.wordpress.com/2012/10/03/regression-testing-api-services-with-restify/#comments</comments>
		<pubDate>Wed, 03 Oct 2012 19:33:09 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/regression-testing-api-services-with-restify</guid>
		<description><![CDATA[Here at Flurry we are big proponents of unit testing and TDD (Test-driven Development) - we believe it makes for tighter code that is less prone to behaving in unexpected ways. We also believe in extensive Regression Testing - making sure the chan...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=164006125&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p class="p1"><span class="s1">Here at Flurry we are big proponents of unit testing and TDD (Test-driven Development) &#8211; we believe it makes for tighter code that is less prone to behaving in unexpected ways.&nbsp; We also believe in extensive Regression Testing &#8211; making sure the changes and code we add don&rsquo;t break existing functionality.</span></p>
<p class="p1">Recently we have begun moving parts of the Flurry backend over to a new set of services running on NodeJs. &nbsp;NodeJS is a fast, flexible application framework that is especially suited to developing RESTful API services.</p>
<p class="p2"><span style="font-size:large;">Restify</span></p>
<p class="p2">To help us build these new backend components we&rsquo;re using the NodeJS &ldquo;<a href="http://mcavage.github.com/node-restify/" target="_blank">Restify</a>&rdquo; framework.&nbsp; Restify provides an extensive amount of low-level functionality to help you correctly implement RESTful services &#8211; much in the same way the &ldquo;Express&rdquo; NodeJS module helps you rapidly develop web-based applications &#8211; for those of you familiar with Express, you&rsquo;d feel right at home in Restify.&nbsp; We&rsquo;ve found Restify to be a fantastic framework for development &#8211; easy to use, understand and implement.</p>
<p class="p2"><span style="font-size:large;">Mocha</span></p>
<p class="p2">To facilitate unit testing, we&rsquo;re using the <a href="http://visionmedia.github.com/mocha/" target="_blank">Mocha Javascript unit testing framework</a> for everything we do and have found it to be flexible and easy to use.&nbsp; Mocha makes it really easy to write unit tests for your NodeJS code &#8211; so easy in fact, we decided we wanted to use Mocha for our regression testing.</p>
<p class="p2">After some trial and error, we have settled on a fairly simple setup, which we have found works well and is easy to implement.&nbsp; The following steps outline the process, and for this small tutorial we&rsquo;ll build the requisite &ldquo;Hello World&rdquo; API that simple returns &ldquo;Hello World&rdquo; when called.</p>
<p class="p2">Before we get started, we first want to make sure that both Restify and Mocha are installed for use in our new Node project:</p>
<p class="p1">
<p><a href="https://gist.github.com/3821529">https://gist.github.com/3821529</a></p>
</p>
<p class="p2">Once those are installed, we&rsquo;re ready to create our sample &ldquo;Hello World&rdquo; API service, as well as setup the Mocha regression test cases.</p>
<p class="p2">Here&rsquo;s the contents of the app.js file that we will be using for testing:</p>
<p class="p2">
<p><a href="https://gist.github.com/3821547">https://gist.github.com/3821547</a></p>
</p>
<p class="p2">You can see that unlike other app.js examples you may have seen, this one is very small and simply makes a function call to StartServer() which has been exported from the start_server.js file.&nbsp; This function simply starts the server &#8211; we&rsquo;ll cover that below.</p>
<p class="p2"><span style="font-size:large;">Start up the NodeJS service in Mocha</span></p>
<p class="p2">Before we can do any regression testing against our &ldquo;Hello World&rdquo; service, we must first start up the Hello World service.&nbsp; To do this, we are going to create a special &ldquo;before&rdquo; Mocha hook &#8211; this will run before any of the other regression test files are run by Mocha, and will allow us to start the service so it can be tested.</p>
<p class="p2">Within your directory, create a sub directory called &ldquo;test&rdquo;.&nbsp; All of our regression test and unit test files are going to be located inside.&nbsp; Create a new file called &ldquo;01-start-server.js&rdquo; with the following contents:</p>
<p class="p2">
<p><a href="https://gist.github.com/3821576">https://gist.github.com/3821576</a></p>
</p>
<p class="p2">This file will be picked up as the first file in the directory (that&#8217;s why we started the filename with 01), and the before() function will be executed, which in turn requires and runs our StartServer() function.&nbsp; &nbsp;The StartServer() function is defined in the start_server.js file:</p>
<p class="p2">
<p><a href="https://gist.github.com/3821649">https://gist.github.com/3821649</a></p>
</p>
<p class="p2">It&#8217;s purpose is to actually initialize the Restify listeners and start the service.</p>
<p class="p2"><span style="font-size:large;">Create a Mocha regression test</span></p>
<p class="p2">Now that we have a way to automatically start the service before we need to test it, we can go about the business of writing our regression test cases.&nbsp; Since our Hello World service is so simple, we&rsquo;re just going to have one test &#8211; we&rsquo;re going to test to be sure our call to the /hello service returns an HTTP response code of &ldquo;200&rdquo;, indicating our request was &ldquo;OK&rdquo;:</p>
<p class="p2">
<p><a href="https://gist.github.com/3821607">https://gist.github.com/3821607</a></p>
</p>
<p class="p1"><span class="s1" style="font-size:large;">Initializing an HTTP Client</span></p>
<p class="p2">At the very top of our file that contains the test cases for our Hello World service you can see we are using a feature of Restify &#8211; the <a href="http://mcavage.github.com/node-restify/#JsonClient" target="_blank">Restify JSON Client</a>.&nbsp; The JSON Client is a small wrapper around NodeJS&rsquo;s http module that makes it easy to call URL based web services that return their content in JSON format.&nbsp; The JSON client will automatically JSON.parse the response body and make it available for your use (as the &ldquo;data&rdquo; parameter in our callback function).</p>
<p class="p1"><span class="s1">Once we&rsquo;ve created our client, we can then use the client to make a GET call to our /hello service URL.&nbsp; If we encounter an error connecting to the service, our &ldquo;err&rdquo; parameter will contain the error.&nbsp; The &ldquo;data&rdquo; parameter will contain the data returned from the call, so we will want to check that to be sure it contains the data we requested.&nbsp;</span></p>
<p class="p1"><span class="s1" style="font-size:large;">Running the Regression Test</span></p>
<p class="p1"><span class="s1">Now that we have our test in place, the next step is to actually run it, which is as easy as typing &#8220;mocha&#8221; in your project directory:</span></p>
<p class="p1"><span class="s1">
<p><a href="https://gist.github.com/3821733">https://gist.github.com/3821733</a></p>
<p></span></p>
<p class="p1"><span class="s1">Mocha will first run the &#8220;01-start-server.js&#8221; file in the test directory &#8211; this starts our service. &nbsp;Next, it will move on to the service_hello_tests.js file and run our solitary regression test. &nbsp;If the service responds as we have outlined in our test, the test will be marked as passed by Mocha.</span></p>
<p class="p1"><span class="s1">Using this simple setup we can add as many additional tests as needed &#8211; either extending our &#8220;hello&#8221; service, or writing additional test cases for new services.</span></p>
<p class="p1"><span class="s1">Using Mocha for both unit testing and regression testing allows us to save time by only having to deal with one testing framework &#8211; Mocha is flexible enough to make running unit tests in more complex scenarios fairly straight forward and easy to do. &nbsp;Now if only it could write your unit tests for you <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/164006125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/164006125/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=164006125&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=5NF2hSdi65A:u1FvO5HLvWo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=5NF2hSdi65A:u1FvO5HLvWo:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/5NF2hSdi65A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2012/10/03/regression-testing-api-services-with-restify/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2012/10/03/regression-testing-api-services-with-restify/</feedburner:origLink></item>
		<item>
		<title>Scaling Build and Deployment Systems</title>
		<link>http://feedproxy.google.com/~r/FlurryTechBlog/~3/pZhKJ_E9Z-4/</link>
		<comments>http://flurrytechblog.wordpress.com/2012/09/18/scaling-build-and-deployment-systems/#comments</comments>
		<pubDate>Tue, 18 Sep 2012 22:39:00 +0000</pubDate>
		<dc:creator>flurrytechblog</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tech.flurry.com/scaling-build-and-deployment-systems</guid>
		<description><![CDATA[Flurry is a rapidly growing company in every meaning of the word including customers, teams, and applications. We have 650 million unique users per month from mobile applications that embed our SDKs which create over 1.6 billion transactions per d...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=161858195&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><span style="font-size:medium;">Flurry is a rapidly growing company in every meaning of the word including customers, teams, and applications.&nbsp; We have 650 million unique users per month from mobile applications that embed our SDKs which create over 1.6 billion transactions per day.&nbsp; Our <a href="http://tech.flurry.com/hadoop-cluster-hardware-management-23838" target="_blank">HBase cluster</a> with over 1,000 nodes holds many petabytes of data and is rapidly growing.</span></p>
<p><span style="font-size:medium;">While Flurry&#8217;s growth is great news for our customers, employees, and investors, it creates challenges for Release Management to support the growing number of applications, the growing number of developers, and the growing number of&nbsp; development and test environments.&nbsp; We need to manage all of that well and do so quickly and reliably.</span></p>
<p><span style="font-size:medium;">In short, we need continuous integration to rapidly build, deploy, and test our applications.</span></p>
<p><span style="font-size:medium;"><strong>Deployment Tools @ Flurry<br /></strong>&nbsp;</span><br /><span style="font-size:medium;">To support our continuous integration, we setup three core tools.</span></p>
<ul>
<li>
<div><span style="font-size:medium;"><strong>Source Control</strong>: We use <a href="https://enterprise.github.com/" target="_blank">Github Enterprise</a> to manage our source code and various configuration files. We use a variation of the Git Flow development process where all features are developed on individual branches and every merge is in the form of a pull request (which is also code reviewed).</span></div>
</li>
<li>
<div><span style="font-size:medium;"><strong>Continuous Build</strong>: We use <a href="http://jenkins-ci.org/" target="_blank">Jenkins</a> to build code and deploy to our QA and test environments and to run our JUnit tests.&nbsp; Jenkins is set up to automatically run JUnit tests when code developers check-in code and when they create pull requests for their branches.&nbsp; Jenkins also runs Selenium tests with SauceLabs every night against the QA environments and Production.</span></div>
</li>
<li>
<div><span style="font-size:medium;"><strong>Task Tracking</strong>: We use <a href="http://www.atlassian.com/software/jira/overview" target="_blank">Jira</a> (with the <a href="http://www.atlassian.com/software/greenhopper/overview" target="_blank">Greenhopper</a> agile plugin) for ticket management for planning and tracking enhancements and bug fixes.&nbsp; All three tools are well integrated with various plug-ins that allow them to share information and to trigger actions.</span></div>
</li>
</ul>
<p><span style="font-size:medium;"><strong>Challenges at Scale</strong></span><br /><span style="font-size:medium;">&nbsp;</span><br /><span style="font-size:medium;">Our setup for continuous integration has served us well but has some challenges.</span></p>
<ul>
<li>
<div><span style="font-size:medium;"><strong>Too Many Jobs</strong>: We have more than 50 Jenkins jobs.&nbsp; We have over 130 deployment scripts and more than 1,600 configuration files for the CI tools and applications.&nbsp; Each new application and each new QA environment adds to the pile.&nbsp; While we are whizzes at writing bash scripts and Java programs, this is clearly not scalable in the long term.</span></div>
</li>
<li>
<div><span style="font-size:medium;"><strong>Slow Deployments</strong>: For security reasons, our Jenkins server cannot deploy war files and config files directly to Production servers.&nbsp; For Production deployments, we run a Jenkins job that copies the files built by other jobs to a server in the data center over a locked-down, one-way secure tunnel.&nbsp; Ops staff then manually runs various scripts to push the files to the Production servers and restart them.&nbsp; This is inefficient in terms of time and people resources.</span></div>
</li>
<li>
<div><span style="font-size:medium;"><strong>Test Overrun</strong>: Our JUnit test suite has over 1,000 test cases which take about an hour to run.&nbsp; With the increase in the number of developers, the number of test runs triggered by their pull requests is clogging the Jenkins build server. We have biweekly releases to Production which we would like to be able to cut down to a daily basis or at least every few days.&nbsp; The blocker to this is that the build, deploy, test, analyze, and fix cycle is too long to allow that.</span></div>
</li>
</ul>
<p><span style="font-size:medium;"><strong>Improving the Process: Design for Speed</strong></span></p>
<p><span style="font-size:medium;">The speed of an engineering team is directly related to the speed of release and deployment so we needed to get faster. We have taken a number of steps to address the challenges.</span></p>
<ul>
<li>
<div><span style="font-size:medium;">We optimized our JUnit test cases by removing unnecessary sleep statements and stubbed out the deployments to our test CDN which reduces network wait time.</span></div>
</li>
<li>
<div><span style="font-size:medium;">We upgraded the build system to bigger, faster hardware and parallelized the JUnit test runs so that we can run multiple test jobs at the same time.</span></div>
</li>
<li>
<div><span style="font-size:medium;">We added dedicated Jenkins slave servers that can share the burden during times of heavy parallel building.&nbsp;</span></div>
</li>
</ul>
<p><span style="font-size:medium;">Overall we have reduced the time to run the entire test suite to 15 minutes.</span></p>
<p><span style="font-size:medium;">To make it easier to manage the Jenkins jobs, we removed a lot of old jobs and combined others using <a href="https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Build" target="_blank">parameterized builds</a>.&nbsp; We renamed the remaining Jenkins jobs to follow a standard naming convention and organized them into tabbed views.&nbsp; We now have a dozen jobs laid out where people can find them.</span><span style="font-size:medium;">
<div class='p_embed p_image_embed'><img alt="Jenkins" height="326" src="http://flurrytechblog.files.wordpress.com/2012/09/jenkins-scaled500.jpg?w=453&#038;h=326" width="453" /></div>
<p></span></p>
<p style="text-align:center;"><span style="font-size:medium;"><em><strong>Jenkins</strong></em></span></p>
<p><span style="font-size:medium;">All of the improvement steps have helped, but we needed more fundamental changes.</span></p>
<p><span style="font-size:medium;"><strong>Improving the Process: RPM Based Software Deployments<br /></strong>&nbsp;</span><br /><span style="font-size:medium;">We changed our build and deployment process to use <a href="http://en.wikipedia.org/wiki/RPM_Package_Manager" target="_blank">RPM repositories</a> where every environment has its own local repository of RPMs.&nbsp; In the new process, the Jenkins job builds the war files then bundles up each war file along with its install script.&nbsp; The job also builds RPMs for each application&#8217;s config files, email templates, data files and the config files for HBase and Hadoop.&nbsp; Once all of the RPMs are built, the job rsyncs the RPMs to the target environment&#8217;s repo.&nbsp; It then runs ssh yum install against each server in the environment to get it to update itself.&nbsp; Once all the servers are updated, the job restarts all of the servers at once.&nbsp; The job is parameterized so that users can build and deploy a single app, a set of apps, all apps, or just some config files.</span></p>
<p><span style="font-size:medium;">The developers have access to Jenkins so that they can update the QA environments at will without having to involve Release Engineering.</span></p>
<p><span style="font-size:medium;">The RPM-based build and deployment process gives us several advantages.&nbsp; The install scripts are embedded into the RPMs which reduces the cluttered hierarchy of scripts called by the Jenkins jobs.&nbsp; The same tools and processes for deployments in the Dev and QA environments can now be safely used in Production.</span></p>
<p><span style="font-size:medium;">By having a repo for each environment, we only have to deploy the RPMs once to that repo.&nbsp; Each sever in the environment then pulls the RPMs from its repo.&nbsp; This save a lot of time and network bandwidth for our remote environments whose servers used to get files directly from Jenkins.</span></p>
<p><span style="font-size:medium;">RPMs support dependencies which instruct yum to deploy a group of other RPMs before deploying the given RPM.&nbsp; For example, we can set an application&#8217;s RPM to be dependent of the application&#8217;s config file RPM, so that when we install the application, yum automatically installs the config file RPM.&nbsp; The dependency feature also allows us to set up a parent RPM for each class of server where the parent RPM is dependent on all of the application RPMs that run on that class of server.&nbsp; We simple execute yum install with the parent RPM, and yum downloads and installs all of the application RPMs and their dependent config file RPMs needed for that server.&nbsp; In the future we will add dependencies for Java, Jetty, and various OS packages to the parent RPMs.&nbsp; This will allow us to kick start a new server and fully provision it at the push of a button.</span></p>
<p><span style="font-size:medium;"><strong>Conclusion</strong></span></p>
<p><span style="font-size:medium;">As with any change in process and tools, there were a few gotchas.&nbsp; The Jenkins slave server was easy to set up, but there were a lot of tools and configurations needed to support our junit test runs that had to be copied from the Jenkins master server.&nbsp; We also found a few places where the concurrent junit tests runs stepped on common files.</span></p>
<p><span style="font-size:medium;">Overall, the changes have sped up and cleaned up our build and deployments.&nbsp; They have allowed us to better manage what we have and to handle our future growth.</span></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/flurrytechblog.wordpress.com/161858195/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/flurrytechblog.wordpress.com/161858195/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=flurrytechblog.wordpress.com&#038;blog=50462819&#038;post=161858195&#038;subd=flurrytechblog&#038;ref=&#038;feed=1" width="1" height="1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=pZhKJ_E9Z-4:T4lWdqCCuzI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/FlurryTechBlog?a=pZhKJ_E9Z-4:T4lWdqCCuzI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/FlurryTechBlog?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/FlurryTechBlog/~4/pZhKJ_E9Z-4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://flurrytechblog.wordpress.com/2012/09/18/scaling-build-and-deployment-systems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cdb8b4c81beb359e92916789c7e969e?s=96&amp;d=identicon&amp;r=G" medium="image">
			<media:title type="html">flurrytechblog</media:title>
		</media:content>

		<media:content url="http://flurrytechblog.files.wordpress.com/2012/09/jenkins-scaled500.jpg" medium="image">
			<media:title type="html">Jenkins</media:title>
		</media:content>
	<feedburner:origLink>http://flurrytechblog.wordpress.com/2012/09/18/scaling-build-and-deployment-systems/</feedburner:origLink></item>
	</channel>
</rss>
