tag:blogger.com,1999:blog-76119152024-03-12T15:58:03.675-07:00WriteBetterBits.com - Jim Fiorato's BlogJim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.comBlogger131125tag:blogger.com,1999:blog-7611915.post-70727676096146552532012-11-30T07:18:00.002-08:002012-11-30T07:23:43.145-08:00Listing AWS EC2 available Linux kernels and ramdisksI can never remember how to do this, and it's not that easy to find, unfortunately:<br />
<br />
<pre class="brush:shell">ec2-describe-images -o amazon --filter "image-type=kernel"
ec2-describe-images -o amazon --filter "image-type=ramdisk"
</pre>
Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com1tag:blogger.com,1999:blog-7611915.post-4180878741659895832011-07-12T07:18:00.000-07:002011-07-12T07:25:08.691-07:00Growl4Rails Forked for JQuery<a href="http://jimhalberg.com/">Jim Halberg</a> (who starred in such films as Gladys the Groovy Mule and The Boatjacking of Supership '79), has ported <a href="http://ajaxian.com/archives/nextpoint-releases-open-source-project-growl4rails">Growl4Rails</a> over to jQuery for your jQuerying pleasure.<br /><br /><a href="https://github.com/jimhalberg/growl4rails">https://github.com/jimhalberg/growl4rails</a><br /><br />Thanks Jim, and enjoy!Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com1tag:blogger.com,1999:blog-7611915.post-42595377520009721642010-06-03T04:41:00.001-07:002010-06-03T04:41:06.009-07:00The Interwebz - Now With 100% More CloudPreservation<p>A couple months ago I suggested that <a href="http://www.writebetterbits.com/2010/03/so-long-finger-poke-later-on-weirdsies.html">I would start blogging more after getting rid of Twitter and Facetube</a>, but wasn't really able to deliver on that promise because we've been working on something really big at <a href="http://nextpointlab.com/">the Nextpoint Lab</a>. Now, I'm real excited that we can let the cat out of the bag and talk about what that is.</p><p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh4.ggpht.com/_6tXqFW_TGFE/TAeUyMSsvTI/AAAAAAAAFis/12E6Eq_h9Zo/Cloud%20Preservation.png?imgmax=800" border="0" alt="Cloud Preservation.png" width="273" height="44" /></p><p>This product we've been working full steam on and now (finally) happy to be announcing in an open beta program is called <a href="http://www.cloudpreservation.com?ref=2104908e532f305">CloudPreservation</a>. And what it provides is a web-based service that automatically crawls your web properties at chosen intervals, building an archive of html source code and resources, high quality snapshots, and a robust full-text search index. The service makes it a breeze to go back in time with all of your web sites, blogs, Facebook fan pages, and Twitter accounts to search content, preview the site, and export data.</p><p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh3.ggpht.com/_6tXqFW_TGFE/TAeUy7CwWcI/AAAAAAAAFiw/qbZfifpVJtg/The%20Fully%20Automated%20Web%20Archive%20Service.png?imgmax=800" border="0" alt="The Fully Automated Web Archive Service.png" width="491" height="537" /></p><p>There's a bunch of reasons why organizations need this service, foremost being regulatory and legal compliance. But another huge one that I think affects this group of folks is backup and business/site continuity, and this works great for keeping a historical archive of the content and (coming soon) images and resources (javascript/css) files from your site.</p><p>Just like our other products, we're leveraging <a href="http://en.wikipedia.org/wiki/Cloud_computing">cloud computing</a> to do the crawling and imaging of these sites, so we're able to scale this out enorumously (and I really mean infinitely) at extremely affordable prices. There's a 30 day free trial, and we've got <a href="http://cloudpreservation.com/pricing.html?ref=2104908e532f305">pricing plans</a> that should suit the needs of any personal blogger who wants some piece of mind, or a huge corporation who can finally be compliant with regulations. We've even got a free plan for those that can get away with it.</p><p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh4.ggpht.com/_6tXqFW_TGFE/TAeUzqn6LuI/AAAAAAAAFi0/J3CLNFPuJkc/screenshot1-1.png?imgmax=800" border="0" alt="screenshot1-1.png" width="635" height="510" /></p><p>We want you to give it a spin. <a href="http://cloudpreservation.com/pricing.html?ref=2104908e532f305">Sign up for a 30-day trial</a> of one of our paid plans, or just take us to the cleaners and pick the free one :). Since we're in beta, I really need your feedback. I know lots of you are some of the most opinionated and nitpicky folks I know, and I want all the nitpicks and opinions because they're super valuable to me, and can really help improve this much needed service. Feel free to give feedback here on the blog, <a href="mailto:jfiorato@gmail.com">send me an email</a>, or send an email to our <a href="mailto:cloudpreservationbeta@nextpoint.com">feedback email address</a>.</p><p>Thanks so much for giving it a whirl!</p>Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com3tag:blogger.com,1999:blog-7611915.post-14744038736102768542010-03-30T19:11:00.001-07:002010-03-30T19:11:38.430-07:00NUMMI<a href="http://www.thisamericanlife.org/">This American Life</a> had a great radio show last week about <a href="http://en.wikipedia.org/wiki/NUMMI">New United Motor Manufacturing, Inc.</a> (NUMMI), which was a joint venture between Toyota and General Motors so that GM could learn the Toyota Production System and so that Toyota could learn how to apply the Toyota Production System in the United States.<br /><br />It's a fantastic show and if you've read <a href="http://www.amazon.com/Implementing-Lean-Software-Development-Concept/dp/0321437381">Implementing Lean Software Development: From Concept to Cash</a> from Mary and Tom Poppendieck, I think you'll really get a kick out of it.<br /><br />Highly recommended.<br /><br /><a href="http://www.thisamericanlife.org/radio-archives/episode/403/nummi">http://www.thisamericanlife.org/radio-archives/episode/403/nummi</a><br /><br />Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-83830625303019421142010-03-30T06:04:00.001-07:002010-03-30T06:04:04.902-07:00So Long, Finger Poke. Later On, WeirdsiesJust about every week, <a href="http://technologyandjunk.com/">Ben</a> and I talk about how this is the week we're done with Facebook and Twitter. We talk about how big of a distraction it is, how little great information we get from it, and how things people say can get us worked up for no great reason. Tired of the .02% of your "friends" who just flood your information streams with useless status updates or political rants.<br /><br />Don't get me wrong, I think that 1-2% of the stuff that I read there is interesting, nice to know or informative. But that's a pretty low hit rate for signal vs. noise.<br /><br />There's this weird and unhealthy emotional attachment to it, which causes me to never hit the off button. Sometimes I feel like I've built up this big property, and I'm scared to just let it go (like there's a bunch of other jfiorato's out there waiting in line for that username). Then there's just the fear of missing something important, that I won't see anywhere else, or that I'll be doomed to find out later than everyone else. <br /><br />But I don't like the way these attachments make me feel. As if we don't have to enough live in fear of these days, fearing that I'm not up to date, or fearing that I'm not marketing myself as well as I could, just isn't necessary anymore. I've just been sick of having so much of my stuff owned by others. Tired of banks owning my shit. Tired of TV owning my CPU cycles. Tired of Facebook and Twitter owning my words and pictures.<br /><br />I feel like I got so much more value out of reading and writing more than 140 characters, but all these 140 character "efficiencies" have ended up paralyzing me.<br /><br />But, still, unready to fully commit to anything, to test things out, <a href="http://technologyandjunk.com/2010/03/26/antisocial-so-long-twitterbook/">Ben and I made a pact</a> to not check Twitter or Facebook for 2 weeks (had our wives change our passwords), and then see where we're at then. Maybe after the two weeks, deleting the accounts, or maybe just leaving them there without knowing the password, not sure yet.<br /><br />So, I'm hoping to pick back up here, and start really writing again.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com3tag:blogger.com,1999:blog-7611915.post-37586757042491217202010-01-09T04:16:00.001-08:002010-01-09T04:16:44.847-08:00What's the Score?Why is it that development teams seem to rarely ever know what the financials look like of the product they are building? Is it that the company doesn't have that information? Unlikely. Is it that it's sensitive information that shouldn't be passed around to just anyone? Maybe. Is it that the company doesn't want to concern the team with all the gory details? Most likely.<br /><br />The ultimate goal of the company is to make more money. Yes, please customers, employ more people are there, but the goal is to make more money. If all your team has for determining success is "on-time delivery" and "quality", the team will end up building process and metrics which may hit the nail on the head for "on-time delivery" and "quality", but my be of poor value when it comes to making more money. Things like "on-time delivery" and "quality" are both obviously going be a positive thing, but the company should draw the line between these metrics and the financials with the development team. The team is smart, and the company should let the team have some input on the metrics that result in making more money.<br /><br />Hiding the financials is hiding score from the team. Like a basketball team that only knew how many times they turned over the ball, or baseball team that only knew how many stolen bases they had.<br /><br />A company can't pretend that the goal isn't anything other than making more money. The team understands that, and wouldn't mind seeing a big fat chart that correlates the fact that they kicked ass to get a feature out in February and with a big spike in sales in July.<br /><br />The team <em>has</em> to know what the score is.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-27843758643972443322009-12-13T05:57:00.001-08:002009-12-13T05:58:46.427-08:00HTPC BuildLast year I decided it was time to update home theater pc. The old one was still on Windows XP with Windows Media Center 2005. The hardware was old and I wasn't really using it much any more, opting to use my cable box w/ much better high definition support.<br /><br />So, I decided to do the build this time on my own, and I thought I'd detail it here for reference.<br /><br />My requirements for the HTPC were:<ul><br /> <li>High definition playback and recording (at least two shows at once)</li><br /> <li>A/V Component Form Factor for Case w/ built in IR Receiver</li><br /> <li>HDMI output to receiver/television</li><br /> <li>Blu-Ray Player</li><br /> <li>Energy Efficient</li><br /></ul><h2>High definition playback and recording (at least two shows at once)</h2><br />For the HD support, I opted to go with the <a href="http://www.amazon.com/dp/B0010Y414Q/">SiliconDust HDHR-US HDHomeRun Networked Digital TV Tuner</a>. I found that this setup (among the many I tried) was the easiest to setup in Windows Media Center. Additionally, you can use the broadcast signal throughout your house on any of your other PCs with <a href="http://www.videolan.org/vlc/">VLC player</a> or other software. This is a fantastic device, and they've got fantastic support.<br /><br /><h2>A/V Component Form Factor for Case w/ built in IR Receiver</h2><br />This was important to me because I didn't want a tower sitting around in my family room. Additionally, I didn't want any more cables that the kids would jack with, so IR receiver cables were not ideal. I chose the <a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16811129054">Antec case</a> for the form factor and IR receiver, but was also pleased with it's cooling capabilities. One downside to this case is that the front display has very very poor contrast, making it difficult to read what's on there from 8' or more.<br /><br /><h2>HDMI output to receiver/television</h2><br />Again, less cables is better. Having the single HDMI out to the receiver, which is forwarded on to the television just makes everything simpler. When shopping for mother boards, I wanted to make sure they had this on board with a decent audio chipset. Asus has a great track record quality mother boards. Downside here is that at the time, there were no HDMI 1.3 mother boards, so audio formats like Dolby True-HD and DTS-HD aren't supported. Looks like you can find HDMI 1.3 capable mother boards now.<br /><br /><h2>Blu-Ray Player</h2><br />Might as well, right? Internal Blu-Ray players only run $50-$60 more than other optical drives. I opted not to get a DVD writer here because I rarely do any DVD writing, and if I did, I'd do it from my laptop and not my HTPC.<br /><br /><h2>Energy Efficient</h2><br />There's a few energy efficient aspects to this PC. First, the motherboard itself supports intelligent standby, which goes bare minimum power until the remote is used or a show needs to be recorded. Second, the chassis and CPU fan speeds are controlled by the motherboard. Third, I installed a 2.5" notebook hard drive for the OS drive, which is far less power hungry than a standard 3.5" disk.<br /><br />So, that's the giddy-up. Happy to field any questions/comments on your own experiences.<br /><br /><h1>Parts List</h1><ul><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16811129054">Antec Black Aluminum / Steel Fusion Remote Black Micro ATX Media Center / HTPC Case</a> - 139.95</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16813131336">ASUS P5Q-EM LGA 775 Intel G45 HDMI Micro ATX Intel Motherboard</a> - 124.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16819115036">Intel Core 2 Duo E8500 Wolfdale 3.16GHz 6MB L2 Cache LGA 775 65W Dual-Core Processor</a> - 189.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16820134582">Kingston 4GB (2 x 2GB) 240-Pin DDR2 SDRAM DDR2 800 (PC2 6400) Dual Channel Kit Desktop Memory Model KVR800D2N5K2/4G</a> - 93.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16822148452">Seagate Momentus 7200.4 ST9160412AS 160GB 7200 RPM 16MB Cache 2.5" SATA 3.0Gb/s Internal Notebook Hard Drive</a> - 53.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16812200176">StarTech 2.5in SATA Hard Drive to 3.5in Drive Bay Mounting Kit</a> - 14.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16822148395">Seagate Barracuda 7200.12 ST3500418AS 500GB 7200 RPM 16MB Cache SATA 3.0Gb/s 3.5" Internal Hard Drive</a> - 54.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16827136162">LG Black 8X BD-ROM 16X DVD-ROM 40X CD-ROM SATA Internal Combo LG Blu-ray Reader & 16X LightScribe DVD±R DVD Burner</a> - 129.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16832116754">Microsoft Windows 7 Home Premium 64-bit 1-Pack for System Builders</a> - 106.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16815116033">Hauppauge WinTV-HVR-1600 ATSC/ClearQAM/NTSC TV Tuner PCI w/Remote 1199 PCI Interface</a> - 84.99</li><br /><li><a href="http://www.amazon.com/dp/B0010Y414Q/">SiliconDust HDHR-US HDHomeRun Networked Digital TV Tuner</a> - 133.00</li><br /><li><a href="http://www.arcsoft.com/en-us/software_title.asp?ProductCode=TMT3P#submenu">ArcSoft TotalMedia Theatre 3 Platinum</a> - 89.99</li><br /><li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16823109163">Microsoft Media Center Keyboard</a> - 39.99</li></ul><br />Total: 1257.84 + Tax + ShippingJim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com3tag:blogger.com,1999:blog-7611915.post-33423808166658978382009-10-24T04:56:00.001-07:002009-10-24T04:56:03.336-07:00Picture Downloader - A Small Study in Affordable ScalabilityScalability always seems to be the poster child for <a href="http://en.wikipedia.org/wiki/You_ain't_gonna_need_it" target="_blank">YAGNI</a>. Lately however, the barrier to entry of scaling out is decreasing as the services that provide elastic infrastructures are wildly abundant. Scaling a website is easier now than ever for just about anyone, but for some reason upfront scalability design seems to still be a bit taboo.<br /><br />I wanted to test how difficult it would be to do upfront scalable implementation, and pay little or nothing until the scaling needed to happen. So, I decided to dive in and see how I would create a site that needed to start with serving a small number of pages, do a little bit of work, and use a little bit of storage, while paying a little bill, but with the ability to scale out the web page serving, the work, and the storage, infinitely.<br /><br />Recently my Dad was asking how to download all the photos from a set in Flickr so he could burn them to a CD for my grandmother. There's a few desktop apps and Firefox extensions for it, but everything requires you to have to download and install software or use a certain browser. So, I thought a web application that looks at a picture site, and zips up the original images in a set or album and let's the user download them would be a good sample application for this test. You can see the application <a href="http://download.fiorato.com" target="_blank">here</a>.<br /><br /><div style="text-align:center;"><a href="http://download.fiorato.com" target="_blank"><img src="http://lh5.ggpht.com/_6tXqFW_TGFE/St22ESES7TI/AAAAAAAAFQs/i7WyN_x4kzM/Screen%20shot%202009-10-20%20at%208.06.54%20AM.png?imgmax=800" alt="Screen shot 2009-10-20 at 8.06.54 AM.png" border="0" width="470" height="284" /></a></div><br /><br /><h2>Overview</h2><br />The application itself can be divided into three parts. The web application, which serves as the interface for both the user and the workers; the workers, which download the images and zip them up; and storage which stores the zipped sets for download.<br /><h2>Web App</h2><br />The web app is a pretty vanilla Ruby on Rails web application. It serves up a single page for the user to enter the information about the set/album they want to download, and it also provides a REST interface for the workers to talk to. This is where the PostgreSQL database resides, and stores the information about the downloads that have been requested.<br /><br />To get cheap scalability, it's deployed to a host called <a href="http://heroku.com/how/architecture" target="_blank">Heroku</a>. Heroku is an infrastructure that provides process-level scaling for web based Ruby applications. When you deploy an application to Heroku, it complies it into a "slug" and this "slug" can be started as a process on a server. Heroku uses <a href="http://aws.amazon.com/ec2/" target="_blank">Amazon's EC2</a> infrastructure and deploys the "slug" to a user-specified number of load balanced processes, with processing slots available across the virtual servers they have running at Amazon. You pay for the number of processes you want to have. 1 process is free, so you can host a low traffic website there for no money at all and scale up the pay scale as you need it.<br /><h2>Workers</h2><br />The workers are Ruby scripts that do the actual downloading and zipping of the set/album. Workers are doing periodic lightweight polling of the web app, looking for new jobs to work on. Once a job is completed the zip is moved to the shared storage, and the worker tells the web app that the job is done and gives the location of the zip file.<br /><br />To get cheap scalability, the workers run on Amazon's EC2 environment. There are two workers per server, and when the Amazon EC2 instance starts up, the code is updated from Git, and the processes are started as service daemons. The EC2 instances are started by the web application, and they shut down after an hour of inactivity. The web application determines how many EC2s to start based upon the number of jobs in the queue. <a href="http://aws.amazon.com/ec2/#pricing" target="_blank">At $.03 per hour</a>, I pay nothing for no activity, and very little as the application scales up.<br /><h2>Storage</h2><br />Since the web app and the workers are physically separated, I needed shared storage that would accommodate for potentially some really large zip files. Additionally, I needed a network that could serve such files reliably for download.<br /><br />To get cheap scalability, I used <a href="http://aws.amazon.com/s3/" target="_blank">Amazon's S3</a> storage for this shared storage. I get great copy speed from the EC2s to the S3 storage, since they're both on Amazon's network, and again, I only pay for what I use. At a minimum, I have to pay for the storage of the EC2 image, and on top of that, I pay for the zip files that are stored there, as well as for the data transfer and requests. You can see the pricing <a href="http://aws.amazon.com/s3/#pricing" target="_blank">here</a>, and you'll see that it's very affordable. The zip files are deleted after a month, to control storage costs.<br /><h2>Conclusion</h2><br />Overall this project took me very little time to do, around 30 hours. With it, I've got a solution that costs me nearly nothing if it isn't used, and would be affordable if it was used quite a bit. That said, it's a pretty simple application, and the lines of separation between web app/workers and storage were very clear, so you're mileage may vary.<br /><br />Also, you probably were wondering about database scaling. In this situation the PostgreSQL scaling would happen vertically, adding more dedicated resources to the database server, rather than more databases to the pool, which<a href="http://support.heroku.com/forums/42309/entries/32362" target="_blank">Heroku supports as well</a>.<br /><br />I do need to give credit to my colleagues at the <a href="http://nextpointlab.com/" target="_blank">Nextpoint Lab</a> who initially put together the scalable design for our software (<a href="http://nextpoint.com/2009_TechnoLawyer_Review/2009_TechnoLawyer_Review.pdf" target="_blank">which gets raving reviews</a>, I'm just sayin'), as it was essentially the blueprint for this design.<br /><br />I think my conclusion is that if the situation is right, upfront design and implementation of a scalable solution doesn't necessarily have to cost you an arm and a leg to get it done, nor does it need to be a huge gamble if the scale isn't needed immediately.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com3tag:blogger.com,1999:blog-7611915.post-25155031755624288532009-07-25T05:41:00.001-07:002009-07-25T05:41:05.773-07:00Are You Following Your Team's Information Stream?If not, you suck. Really, you do. You sucky suck suck. You're a bad, bad manager. Sorry to be the bearer of bad news.<br /><br />It's sad really, because you've got a great team, that's filling the atmosphere with fantastic information, and you're not taking the time to soak it in. Chances are, most people on your team are on Twitter. Also chances are there's a solid percentage of your team that's got a blog somewhere. This is likely the most valuable information that you can possibly consume. But you don't, so you suck.<br /><br />I don't think you're alone though... I think that most manager's only hook into their team's digital personality is IM status, and that's just sad (though, I've seen some really good IM statuses). But, did you know that your most introverted engineer has 3,000 status updates on <a href="http://twitter.com/">Twitter</a>? Did you know that your Project Manager has a blog about <a href="http://www.haskell.org/">Haskell</a> coding? Did you know that your QA engineer is a semi-pro <a href="http://www.youtube.com/watch?v=BCzrUzlX6P8">kickboxer</a>?<br /><br />Your team is giving you feedback, intentionally, indirectly. I think it's time that you need to accept the fact that this stream is like a uber-informative <a href="http://www.liveleak.com/view?i=5b5_1181060988">facial expression</a>. Your team is letting you know how their day went, what they think you're doing wrong (or right), and what they think the company is doing wrong (or right). Maybe it's a bit passive aggressive, but who cares if they're telling you something that you should be hearing? Is there really a better channel for them?<br /><br />As a manager, you've always got time to learn more about <a href="http://en.wikipedia.org/wiki/Software_Craftsmanship">the craft</a>, practices, people... And your team member's streams are full of great information about it. Believe it or not, they're thinking about work just as much as you.<br /><br />Your team is likely doing very, very interesting stuff outside of work. Having an idea of what that is, and showing that you're interested in it goes a long way toward strengthening your relationship. Think about walking in on a Monday morning and saying "Saw you went hand gliding, how awesome was that?" instead of sounding like a fucking tool at the water cooler saying "How was your weekend?" and getting the same old "Good, yours?", followed by the awkward silence then "ok, have a good one". Get involved, and you'll have something interesting to talk about.<br /><br /><strong>Your team would appreciate it.</strong> As a manager, your team looks up to you, and them knowing that you're paying attention and interested in what their doing, makes them feel appreciated. The more they do to feel appreciated through this information stream, the better off everyone is. You're all growing.<br /><br />So, here's the good news; I can retract the sucky bad manager claim if you start following your team's information stream today. Do it, or you still suck.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com4tag:blogger.com,1999:blog-7611915.post-44169668336892584052009-07-21T09:22:00.000-07:002009-07-21T09:26:19.226-07:00Response From programmer.grrlYou should read Amy G's response to my last post:<br /><br /><a href="http://programmergrrl.blogspot.com/2009/07/companies-are-addicted-to-profit-like.html">Companies are Addicted to Profit Like Smokers are Addicted to Nicotine?</a><br /><br />It's good.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-80221877487654697142009-07-20T05:11:00.001-07:002009-07-20T05:11:40.983-07:00Define success...<a href="http://twitter.com/programmergrrl">Amy G</a> wrote a <a href="http://programmergrrl.blogspot.com/2009/07/what-if-your-unsuccessful-project-wasnt.html">response to my post</a> about why I think that <a href="http://www.writebetterbits.com/2009/07/large-scale-project-doesn-equal-large.html">large development projects don't work</a>.<br /><blockquote>My concern is, so what? Just because a project fell short of what was envisioned, blew the timeline, or damaged the team, does that mean it wasn't successful?</blockquote><br />My answer to that, is, no, it doesn't mean that at all. But only along the same lines as: If you smoke a pack of cigarettes today, does that mean it's going to kill you? No, it probably won't. You'll likely live, but, you'll also likely smoke another pack tomorrow, and the next day, and then the answer changes.<br /><br />Now, as if it wasn't bad enough that I equated large development projects to smoking cigarettes, I'm going to quote <a href="http://www.amazon.com/Peopleware-Productive-Projects-Teams-Second/dp/0932633439">DeMarco and Lister</a>, who I think she feels are icons of an unattainable utopian relationship between management/organizations and the folks in the trenches (but I don't want to put words in her mouth, you should ask her yourself).<br /><blockquote>Historians long ago formed an abstraction about different theories of value: The Spanish Theory, for one, held that only a fixed amount of value existed on earth, and therefore the path to the accumulation of wealth was to learn to extract it more efficiently from the soil or from people's backs. Then there was the English Theory that held that value could be created through ingenuity and technology. So the English had an Industrial Revolution, while the Spanish spun their wheels trying to exploit the land and the Indians in the New World. They moved huge quantities of gold across the ocean, and all they got for their effort was enormous inflation (too much gold money chasing too few usable goods).</blockquote><br />Value in software comes from having a great understanding of the domain and the gap that the software is trying to fill, and coming up with innovative and smart solutions to fill that gap. Innovations and smart solutions don't come from people who are constantly working overtime, or constantly feeling defeated because of another missed timeline or unrealized feature.<br /><br />But value in software is hard to gauge, especially when something of lower value can sell really well in the immediate future. Some businesses are great at selling products that are of lower value. But without value, any success will always be fleeting.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com1tag:blogger.com,1999:blog-7611915.post-27339304817799147722009-07-09T04:08:00.001-07:002009-07-09T04:11:39.209-07:00Merge Tracking with Subversion 1.5A year or so ago, a few of us at the office piled into a conference room to watch a webinar about all the new features Subversion 1.5. One of those features that sounded cool, but was conceptually opaque to me, was <a href="http://subversion.tigris.org/merge-tracking/">merge tracking</a>. But, recently, I've had to get my merge on, and wanted to see what it was all about, and it was one of things I'd wished I'd taken the time to do sooner.<br /><br />The bottom line, is that now Subversion actually has a workflow for <a href="http://svnbook.red-bean.com/en/1.5/svn.branchmerge.basicmerging.html#svn.branchemerge.basicmerging.stayinsync">keeping your branch in sync with the trunk</a>, so you've got less surprises when it's time to put your work back into the trunk. You no longer need re-branch in order to get the latest trunk changes for your branch. You can just tell SVN to get any changes from the trunk since you either made the branch, or last took changes from the trunk.<br /><br />The workflow is pretty simple. You make your branch, you work on it for a while, you say, "I'm going to be merging into the trunk eventually, I'd better make sure that goes smoothly." so you update your branch with the latest from the trunk:<br /><br /><pre class="brush:shell"><br />$ pwd<br />/home/user/my-calc-branch<br /><br />$ svn merge http://svn.example.com/repos/calc/trunk<br />--- Merging r345 through r356 into '.':<br />U button.c<br />U integer.c<br /></pre><br /><br />So, since we didn't specify revisions, you can see that Subversion is fully aware of what revision of the trunk your branch came from. Also, Subversion is going to store all the revisions that you've just merged into your branch. You can do this to see:<br /><br /><pre class="brush:shell"><br />$ cd my-calc-branch<br /><br />$ svn mergeinfo http://svn.example.com/repos/calc/trunk<br />r341<br />r342<br />r343<br />…<br />r388<br />r389<br />r390<br /></pre><br /><br />You can also see which changes from the trunk that you're missing:<br /><br /><pre class="brush:shell"><br />$ svn mergeinfo http://svn.example.com/repos/calc/trunk --show-revs eligible<br />r391<br />r392<br />r393<br />r394<br />r395<br /></pre><br /><br />So, you can repeat this process often, which I'd recommend. The more frequently you integrate the changes from the trunk, the more unicorns and rainbows come merge time.<br /><br />Another benefit of Subversion keeping the merge information around, is that you can undo merges:<br /><br /><pre class="brush:shell"><br />$ svn merge -c -303 http://svn.example.com/repos/calc/trunk<br />--- Reverse-merging r303 into 'integer.c':<br />U integer.c<br /></pre><br /><br />This is just for keeping your branch in sync with the trunk. How bout when you want to move your changes into trunk when your work is complete? Well, all this merge history will be taken into account when you decide to merge back into the trunk. Subversion will understand what has already been pulled in from the trunk (or any branch for that matter), and only merge the revisions that aren't in the merge history.<br /><br />This is a very handy feature, it's a shame I waited this long to dive in.<br /><br />(Note: all these examples I shamelessly copied from the <a href="http://svnbook.red-bean.com/en/1.5/">svn book</a>)Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-16716991068350429782009-07-06T05:08:00.001-07:002009-07-06T05:08:07.434-07:00Large-Scale Project Doesn't Equal Large-Scale Development<a href="http://www.jeffsmall.com/">Jeff</a> and I were have a discussion on Twitter last month around <a href="http://www.37signals.com/svn/">37signals</a>' "<a href="http://gettingreal.37signals.com/toc.php">Getting Real</a>" philosophy. Specifically, <a href="http://technologyandjunk.com/2009/06/16/make-plans-but-dont-tell-anybody/">Ben's post</a> initiated the conversation, and his post was based on <a href="http://www.37signals.com/svn/posts/1750-the-planning-fallacy">this one from Signal vs. Noise</a>. What we were discussing was how the "Getting Real" philosophy applies (or doesn't) to other organizations that have justifiably complicated problems to solve, or have to work with legacy systems, or have to deliver up front estimates on work to be completed, or have a QA team.<br /><br />My point was that ultimately, "Getting Real" is delivered in an <a href="http://www.writebetterbits.com/2009/02/foolish-writers-and-readers-are-created.html">extremely prescriptive manner</a> by the folks at 37signals. Their philosophy is contrived in a vacuum that they've built with well-packaged and well-priced software, which I'm sure they worked very hard to create, but, unfortunately, that model isn't in the stars for everyone.<br /><br />Eventually, our Twitter conversation ended on me promising Jeff a blog post on why I thought "Getting Real" <em>does</em> apply to large scale development. The reason is that we need to stop thinking that large scale development is necessary. Just because the project may be relatively large, the development doesn't need to be equivalently large. The concept of parallelizing development with a large team to deliver a large amount of code for a large project all at once, is in my opinion, well... broke.<br /><br />The only successful large projects I've been a part of have consisted of small development releases. Small teams focused on single or few chunks of functionality delivered in short iterations, with the team <a href="http://www.infoq.com/articles/real-options-enhance-agility">deferring as many of the decisions as late as possible</a>. And this is where I think the "Getting Real" philosophy fits in really well, and works well even if it doesn't fit into the other aspects of the organization.<br /><br />Take "large scale development" off the table, eliminate it from your vocabulary. Keep it short and sweet, even if the rest of your organization can't be that way.<br /><br />With the "large scale development" mind set, the odds are stacked against you. You'll find that you've fallen short on what you've envisioned, fallen short on your timeline, and probably done some irreparable damage to your talented team. <br /><br />Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-32653828325911774722009-03-14T07:42:00.001-07:002009-07-07T04:25:51.784-07:00Memoization with JavascriptMemoization is somewhat common optimization where the results of a function are cached, so that subsequent calls to that same function, with the same arguments can skip the execution and return the object from cache. With interpreted languages, the savings of memoizing frequently called funcitons with a limited domain of arguments can save quite a bit of execution time. Obviously, you need to balance this speed with the amount of memory that your page will consume. Finding DOM objects is a pretty good application of memoization.<br /><br /><pre class="brush:js"><br />function memoize(obj, func) {<br /> the_func = obj[func];<br /> cache = {};<br /> <br /> return function() {<br /> var key = Array.prototype.join.call(arguments, '_');<br /> if (!(key in cache))<br /> cache[key] = the_func.apply(obj, arguments);<br /> return cache[key];<br /> }<br />}<br /><br />var ElementFinder = {<br /> findById: function(id) {<br /> console.log('Calling Function with id: %s', id);<br /> return document.getElementById(id);<br /> }<br />}<br /><br />ElementFinder.findById = memoize(ElementFinder, 'findById');<br /><br />function load() {<br /> for(var i=0;i<10;i++) {<br /> console.log(ElementFinder.findById('my_div').id);<br /> }<br />}<br /></pre>Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com1tag:blogger.com,1999:blog-7611915.post-5471563883435522042009-03-10T06:36:00.001-07:002009-03-10T06:50:02.353-07:00How Firefox 3.1 Uses Trace Trees to Optimize Javascript Runtimes<a href="http://www.mozilla.com/en-US/firefox/all-beta.html">Version 3.1 of Firefox</a> should be a pretty marked improvement for Javascript performance because of a compilation optimization that the Firefox team is putting in place for that release. Trace-based compilation identifies loops, and records frequently visited paths within those loops to determine what needs to be compiled.<br /><br />Traditional Just-In-Time compilation usually happens at the method/function level, where the need for compilation is simply determined by whether or not the function/method has been visited. When a function is visited for the first time, the control flow graph for the entire function is created, then compiled into the proper instruction set. This could cause quite a bit of unnecessary overhead given the way that Javascript applications are delivered via the internets.<br /><br />With trace compilation, the compiler first determines the loop headers, since most frequently called code usually exists within a loop. To determine loop headers, the compiler keeps a counter of back branches (ones that send control back to a previous location), and once that counter hits a certain threshold, that is identified as a "hot" trace. Subsequent paths starting at that loop header are then recorded and compiled.<br /><br />In this scheme, the interpreter and the compiler are handing control back and forth to each other, which itself can be somewhat expensive. However, all along the way, whenever interpretation of a branch is occurring within these "hot" traces, the recorder is keeping track and compiling the alternate paths.<br /><br />There's a bunch more <a href="http://www.hpl.hp.com/techreports/1999/HPL-1999-78.pdf">information on this method of compilation</a>, including information that's <a href="http://www.ics.uci.edu/~franz/Site/pubs-pdf/ICS-TR-07-12.pdf">specific to TraceMonkey implementation</a>.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-70383045978506985172009-02-28T06:50:00.000-08:002009-07-07T04:36:48.728-07:00Manipulating scope with the Javascript "with" statementThe <span style="font-family:courier new;">with</span> statement in Javascript allows you to tack the scope from an expression into the current execution context. It's really similar to the VB With statement. Here's a simple example:<br /><pre class="brush:js">function showDivStyle(){<br /> <br /> with($('my_div')) {<br /> console.log(style.backgroundColor);<br /> }<br />}<br />showDivStyle(); //logs the string "yellow" at this point.<br /></pre>It gets even more interesting when you combine it with a closure, as the scope is extended even more.<br /><pre class="brush:js">function showDivStyle(){<br /> var myClosure;<br /> <br /> with($('my_div')) {<br /> myClosure = function() {<br /> console.log(style.backgroundColor);<br /> }<br /> }<br /> <br /> return myClosure;<br />}<br /><br />theClosure = showDivStyle();<br />theClosure(); //logs the string "yellow" at this point.<br /></pre>Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-14381253126148017672009-02-28T05:08:00.001-08:002009-07-07T04:41:33.590-07:00Growl4Rails - Rails == Growl4???I've had a few people ask how to setup Growl4Rails without using rails. It's pretty easy as is, although you may be a little miffed by the directory structure. Feel free to go in and munge with the source if you'd like it to be more flexible, or to update it to suit your needs. All of the path dependencies are in the CSS files.<br /><div><br /></div><div>First, grab the source from GitHub:<br /><pre class="brush:shell">git clone --depth 1 git://github.com/jfiorato/growl4rails.git</pre>After that, create and images/growl4rails, javascripts/growl4rails, and stylesheets/growl4rails directories under your public folder.<br /><br />From the Growl4Rails source, copy the contents of the public/javascripts, public/images, and public/stylesheet directories to your newly created folders, respectively.<br /><br />Then, make sure to copy prototype.js and effects.js to your javascripts directory.<br /><br />Once all the resources are there, all you need to do is add the includes to your layout/masterpage/template:<br /><pre class="brush:js"><br /><script src="javascripts/prototype.js" type="text/javascript"></script><br /><script src="javascripts/effects.js" type="text/javascript"></script><br /><br /><script type="text/javascript" langauge="javascript"><br /> var growl4rails_duration = 5000;<br /> var growl4rails_max_showing = 5;<br /></script><br /><br /><script src="javascripts/growl4rails/growl4rails.js" type="text/javascript"></script><br /><link href="stylesheets/growl4rails/growl4rails.css" media="screen" rel="stylesheet" type="text/css"><br /></pre><br /><br /></div>Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-21074273503728802882009-02-27T19:36:00.000-08:002009-02-27T20:38:23.956-08:00Foolish writers and readers are created for each other<div>Probably like a lot of people, <a href="http://blog.objectmentor.com/articles/2009/01/31/quality-doesnt-matter-that-much-jeff-and-joel">the hoo-ha between Atwood/Spolsky and Robert Martin</a> on the importance of code quality and unit tests has had me thinking a lot lately. But it's not the suggestion code quality is of little value, or that writing unit tests are thriftless that was the subject of my reflections.<br /><br />What's got me thinking about it all, is how both sides of the argument are extremely anecdotal. Atwood, Spolsky and Martin are all being very prescriptive about subjects that are extremely idiosyncratic, and these guys professionally represent two extreme ends of the programming spectrum; big company consulting and small team software R&D. I'd even go so far as to say they are different professions.<br /><br />Anyway, I've come to the conclusion that I need to be more careful when being so prescriptive in my writing, and I need to do a much better job at qualifying my opinions on not-so-cut-and-dry matters.<br /></div><div><blockquote><br />"Foolish writers and readers are created for each other."<br />- Horace Walpole</blockquote></div>Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com0tag:blogger.com,1999:blog-7611915.post-18636436537107583972009-02-27T06:18:00.000-08:002009-02-27T07:46:16.297-08:00Working Remotely SuccessfullyBefore I started here at <a href="http://nextpoint.com/">Nextpoint</a>, I had some doubts that working remotely would work out all that well. Yes, not having to put pants on in the morning and being able to make a trip to the pantry every half hour for more Thin Mints certainly has it's appeal, but I was worried about being "That guy in Chicago".<br /><br />However, 4 months in, and I've been extremely happy with the way it's all panned out. I think there's some key arrangements and tools that we've had in place that have made it successful. Keep in mind that our team is small, 4 people (not including me), so your mileage may vary.<br /><h2>Regularly make trips to see the team in person</h2>This is the most important thing, as it allows me to personally connect with the team. We get a meal or two in, get the water cooler talk in, and we can get the personal connections together. I'll usually take some time as well to give the team a tour of what I've been working on.<br /><br />I've found that if I don't make these trips regularly, I'll start to feel disconnected, and actually start becoming a little distressed. Being up there lets me tap into the vibe, and gets me pumped about what I'm doing. I'm fortunate enough to be able to do it every other week, since the office is in driving distance and I can keep the trips to a single day. But, I think that if the distance were greater, once a month or once every two months would be a good interval as well.<br /><h2>Group chat is a must</h2>Group chat is a key tool that has made working remotely successful. <a href="http://blog.justingreer.com/"> Justin</a> found a fantastic <a href="http://blast.aim.com/?icid=aimblastaimcom">group chat feature of AIM</a> that allows you to create a group then invite other AIM screen names to be members of this group. Each AIM screen name adds the group as a buddy. Then all instant messages are blasted out to each of the members. This eliminates the need to organize everyone into the chat, and just lets you chat and whoever is online gets the messages.<br /><br />We had also tried out <a href="http://www.yammer.com/">Yammer</a>, but we weren't all keen on more apps/configurations/browser tabs in order to use the tool. We already use Adium, so just adding another account was simple.<br /><h2>Daily IN/OUT status</h2>Being remote, it's hard to know what everyone is working on. It's also equally difficult to let everyone know that you're making progress. I wanted to let everyone know that I wasn't just sitting at home and watching Days of Our Lives.<br /><br />Providing "what I'm going to work on today" when we get in, and a "here's what I did today" is a great way to keep up with what everyone is working on. We've been using <a href="http://www.basecamphq.com/">Basecamp</a> for tasks and Wiki, and with it, you get a group chat tool <a href="http://www.campfirenow.com/">Campfire</a>. This is different than the AIM tool, because there's a history kept, and you don't have to be online to catch up. This way, I can see what everyone else is working on, and what they've done. If we didn't have Campfire, a tool like Yammer could work well.<br /><h2>Video conferencing isn't necessary</h2>When I first started, I thought for sure that we'd need a video/audio conference solution as well as a virtual white board. At first I tried to make a point of it to call with <a href="http://skype.com/">Skype</a>, but that was difficult to do as a group (plus video of of me with my cat humping the bed in the background was a little difficult for the rest of the team to watch). So then I bought a <a href="http://www.ipevo.com/products/pro_detail.php?id=10">Skype speaker phone</a>, which ended up being a waste of money. Then Justin (we call him MacGreerver) <a href="http://jameshalberg.com/2008/11/24/speaker-phone/">crafted a speaker phone out of an old set of iPod headphones</a>, which worked 100x better than the $160 speakerphone I purchased.<br /><br />We haven't used any of these things in a couple of months now. The AIM group chat has completely made this unnecessary. Any time we need to talk one on one, we chat. When we need to talk as a group, we group chat. When we need to leave status, we use Campfire.<br /><br />These tools and ideas have really made working remotely successful. If we adopt any new tools or ideas, I'll make sure to update this post.<br /><br />So, as I sit here, with no pants on and minty-chocolate breath, I'm extremely happy that I gave it a try.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com6tag:blogger.com,1999:blog-7611915.post-72613861837108798702009-01-21T05:36:00.001-08:002009-07-07T04:45:40.658-07:00Update to Growl4RailsGrowl4Rails is now production ready. I've added the ability to show multiple growls at once, as well as improved support for IE. Here's a screen shot of the multiple Growls:<br /><br /><img src="http://lh4.ggpht.com/_6tXqFW_TGFE/SZwZMujJ1zI/AAAAAAAAEIg/hPaDBZCWgVs/s800/Picture%201.png" /><br /><br />Unfortunately, the multiple growls thing was an entire rewrite of the code, so the usage is quite different.<br /><br />Now, when you setup the includes, you specify default duration and max number of growls to show. These arguments are optional and will default to 3000 milliseconds and 3, respectively.<br /><pre class="brush:js"><br /><%= growl4rails_includes(3000, 5) %><br /></pre><br />Also, when showing the growls, the args are now a single hash, with named keys:<br /><pre class="brush:js"><br /><script type="text/javascript" language="javascript"><br /> Growl4Rails.showGrowl({<br /> image_path:"/images/download.png", <br /> title:"Foo Bar.pdf", <br /> message:"File is ready for download."<br /> });<br /></script><br /></pre><br /><br />When you want to handle the click event, you can wire up the event like so:<br /><pre class="brush:js"><br /> var growl_id = Growl4Rails.showGrowl({<br /> image_path:"/images/download.png", <br /> title:"Foo Bar.pdf", <br /> message:"File is ready for download."<br /> });<br /> document.observe(growl_id + ':clicked', function(event) {<br /> console.log('Growl %s was clicked.', Event.findElement(event).id);<br /> });<br /></pre><br />Again, it's open source, so if you want to contribute, or if you have any feedback, you can check out the project on <a href="http://github.com/jfiorato/growl4rails">GitHub</a>.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com31tag:blogger.com,1999:blog-7611915.post-33481307370509273362009-01-17T07:08:00.001-08:002009-07-07T04:47:15.030-07:00Javascript TemplatingWriting HTML with Javascript has always been a necessary evil, and for me a painful thing to look at in code. Usually we have to do this when we've got some set of data in a collection on the client, and we need to loop through the collection and build HTML.<br /><br />Back in the day, before I was privy to Javascript templating, I'd do this:<br /><pre class="brush:js"><br />var myArray = ['John', 'Steve', 'Bill'];<br />var myHTML = '';<br />for(i=0;i<myArray.length;i++) {<br /> myHTML += '<div>Hello, my name is ' + myArray[i] + '.</div>';<br />}<br />var container = document.getElementById('myContainer');<br />container.innerHTML = myHTML;<br /></pre><br />There's a few things wrong with this. It's everything bad about the <a href="http://en.wikipedia.org/wiki/Separation_of_concerns">close intermingling of two different languages</a>, or having one language write the other. It's also extremely inefficient. The <a href="http://blogs.msdn.com/jscript/archive/2007/10/17/performance-issues-with-string-concatenation-in-jscript.aspx">concatenation of the string</a> results in 3 additional strings allocated during each iteration. And finally, what if my data structure gets more complicated (which in this case, there's no doubt it will), and the array becomes multi-dimensional, then this code gets even more gnarly.<br /><br />Today, with the arrival of Javascript frameworks like <a href="http://prototypejs.org/">Prototype</a>, <a href="http://jquery.com/">jQuery</a> and <a href="http://dojotoolkit.org/">Dojo</a>, doing this work becomes not only trivial, but much better performing. I'm going to use Prototype for my examples here, but you'll find the other frameworks only differ slightly in semantics.<br /><pre class="brush:js"><br />//use a more descriptive structure<br />var myData = [{name: 'John'}, {name: 'Steve'}, {name: 'Bill'}];<br /><br />//Template is a Prototype class<br />var template = new Template('<div>Hello, my name is #{name}.</div>');<br /><br />//each is a handy Prototype array extension<br />myData.each(function(item) {<br /> //the $('foo') syntax is Prototype shorthand for getElementById.<br /> $('myContainer').insert(template.evaluate(item));<br />});<br /></pre><br />Definitely a much cleaner approach here. With the old way of doing things, as the complexity of what you have to display grows, the complexity of the code is exponential. However, with the template approach, complexity is closer to linear.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com1tag:blogger.com,1999:blog-7611915.post-63474218563969235102008-12-25T07:09:00.001-08:002008-12-25T07:25:11.995-08:00Giving Open Source for Christmas - Growl4Rails Plugin<a href="http://github.com/jfiorato/growl4rails" target="_blank">Growl4Rails</a> is a javascript component that provides the UI for growl-like notifications in your Rails application.<br /><br />This plugin requires Prototype 1.6 or higher and Scriptaculous 1.7 or higher.<br /><br /><img src="http://lh4.ggpht.com/_6tXqFW_TGFE/SVOfpXw_ZII/AAAAAAAAD5o/-oVi5h-b7bE/s400/%5BUNSET%5D.png" /><br /><br /><h2>Installation</h2><br />If you are on Rails 2.1 or higher:<br /><pre>$ script/plugin install git://github.com/jfiorato/growl4rails.git</pre><br />For older versions of Rails, cd into your application's vendor/plugins, and execute the following:<br /><pre>$ git clone --depth 1 git://github.com/jfiorato/growl4rails.git<br />$ mkdir ../../public/javascripts/growl4rails ../../public/stylesheets/growl4rails ../../public/images/growl4rails<br />$ cp growl4rails/public/javascripts/* ../../public/javascripts/growl4rails/<br />$ cp growl4rails/public/stylesheets/* ../../public/stylesheets/growl4rails/<br />$ cp growl4rails/public/images/* ../../public/images/growl4rails/</pre><br /><h2>Usage</h2><br />In your view put the following:<br /><pre><%= growl4rails_includes %></pre><br />Then when you'd like the Growl window to appear:<br /><pre>//javascript<br />Growl.show("/images/download.png", "Foo Bar.pdf", "File is ready for download.", 5000);</pre><br />Growl.show method takes 4 arguments:<br /><pre>image - 32x32 icon<br />title - title of the growl<br />message - the growl message<br />duration - the length of time (in milliseconds) that the growl window shows</pre><br /><br />It's definitely got some kinks, but I'm working those out. Obviously, if you'd like to contribute, feel free!Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com3tag:blogger.com,1999:blog-7611915.post-55383394094777083552008-12-21T14:44:00.001-08:002008-12-21T14:44:14.842-08:00Building Something Other Than SoftwareOk, so this doesn't have much to do with bits, but it does have to do with building things.<br /><br />My wife got the idea (for me) to build Harvey (2 1/2) a kitchen for X-Mas this year. She got the idea from <a href="http://www.ohdeedoh.com/ohdeedoh/how-to/how-to-build-a-play-kitchen-from-ikea-components-066719">Apartment Therapy</a>.<br /><br /><img src="http://lh6.ggpht.com/_6tXqFW_TGFE/SU7FQuS1a7I/AAAAAAAAD44/mPBdTQ8hPcY/s512/DSC_3759.JPG" alt="DSC_3759.JPG" border="0" width="340" height="512" /><img src="http://lh3.ggpht.com/_6tXqFW_TGFE/SU7GDNfgJJI/AAAAAAAAD5A/csWHPipTgjY/s512/DSC_3760.JPG" alt="DSC_3760.JPG" border="0" width="340" height="512" /></div><br /><br />I mostly followed what was described there, but embellished a little bit on the door and shelves and added a bit of structural support. All in all, with pots and pans and utensils it cost about a $100.<br /><br />Fun project.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com2tag:blogger.com,1999:blog-7611915.post-43522295241464360542008-12-04T19:25:00.001-08:002008-12-04T19:25:48.292-08:00More CatsFletcher thinks I need more cats on my blog. Here you go!<br /><br /><img src="http://lh4.ggpht.com/_6tXqFW_TGFE/STifELqL5zI/AAAAAAAADDw/B9mT0_ApPWY/spaghetti-cat.jpg?imgmax=800" alt="spaghetti-cat.jpg" border="0" width="600" height="441" />Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com2tag:blogger.com,1999:blog-7611915.post-43810480567984975572008-11-28T06:04:00.001-08:002008-11-28T06:04:36.561-08:00Flow - Building Lean TeamsThere's few things more detrimental to the productivity of your thought workers than the interruption of flow, yet I think that so few teams recognize its importance. <a href="http://www.amazon.com/Peopleware-Productive-Projects-Teams-Second/dp/0932633439">Demarco and Lister</a> describe flow as<br /><blockquote>"a condition of deep, nearly meditative involvement"</blockquote><br />Flow is a requirement in what we do. It's extremely productive time that increases quality, creativity and an overall feeling of accomplishment at the end of the day. For most, this state of immersion takes a bit of time to get into, but takes a split second to get out of. <br /><br />In my experience, email and IM are disruptions that you can more easily tune out, or just flat out remove by turning them off. But the biggest disruption of flow that I've come across is when someone stops by a co-worker's desk with a "Hey, do you have a second?" Instantly the flow is lost. Your second is given to that person, at the expense of 15 minutes more of your time to get immersed again.<br /><br />Say you have 5 of those interruptions a day (which is probably pretty conservative for most people), you've got nearly and hour and a half of interruptions. Tack on a few meetings, and you've got a half of a day of productive time on what was scheduled at 8 hours.<br /><br />If you have taken the time to recognize this issue, often times what the response is, is to start padding scheduling. You start to say, "Jim is only productive 50% of the day". This results in timelines being pushed out or features being cut, and the overall sense that it takes forever to get stuff out the door. Not only that, but Jim doesn't want to be 50% productive. He want's to be 100% productive. He wants to feel like he knows where his day went.<br /><br />It's easy to measure your flow. You can count the number of uninterrupted work hours per day. If you make it from 9-11 AM without an interruption, you've got 2 hours of uninterrupted flow. I'd challenge you to try measuring that with your team. I'd bet you'd be surprised at the ratio of uninterrupted hours to hours worked.<br /><br />What can you do to curb interruptions? Designate certain hours in the day when people are "publicly available". Organize your space so that it's conducive to flow and impedes interruption. <br /><br />If you need to make a case to higher-ups on the impact of flow, you can try measuring a developer who has usually low uninterrupted work hours, and put them up in an office for a week. Measure their uninterrupted work hours then. Say that they usually have 3 uninterrupted work hours for every 8 they work when they aren't in an office, but they've got 6 uninterrupted for every 8 that they work when they are in an office. By rearranging you've made them 50% more productive.<br /><br />Protect the flow.Jim Fioratohttp://www.blogger.com/profile/04111942317657114808noreply@blogger.com3