<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6197006951470169345</id><updated>2011-10-02T19:15:10.160-07:00</updated><title type='text'>Tom Finnigan's Tech blog</title><subtitle type='html'>I'm a programmer, primarily c++.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-8729750664467831827</id><published>2009-06-26T10:13:00.000-07:00</published><updated>2009-06-26T10:29:22.854-07:00</updated><title type='text'>Very Sleepy Profiler</title><content type='html'>So, lately at work I've been working on the performance of our product.  One of the first steps to improving speed is to run a profiler.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I've been completely spoiled by shark, the free profiler available on OSX.  It's a sampling profiler, but it also does stack sampling, and works great.  You just attach to any running program (or launch a program) and it runs at roughly the original speed, but gives you lots of great information.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I was looking for a shark-like profiler for windows and I tried lots - VTune, Intel's PTU, Windows Performance Toolkit, GlowCode, and a few others.  Eventually I ended up with a profiler called &lt;a href="http://www.codersnotes.com/sleepy/"&gt;Very Sleepy&lt;/a&gt;.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Very Sleepy has several advantages.  I don't want an instrumented profiler, because with a UI-heavy app, instrumentation makes profiling unfeasibly slow. You either have to program a UI-using robot, or be very very patient in using your UI.  Since we're a plugin, the UI robot would be much more complicated than just using a sampling profiler.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Next, it provides exactly the information I want to know - what's the hotspot?  How is it being called?  What does it call?  For each function, how much does it represent, by itself and with children?&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Finally, it's open-source, so it's free, and I can modify it to meet my requirements.  I was having lots of problems getting it to properly load the symbols from our symbol server and over the internet, but because I had the source, it was simple to dump debugging information.  There are a few other small customizations that I've been able to make to help our usability (i.e. only look at processes with an image starting with the letter R) that are only really beneficial to me and my coworkers.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The main hiccup I found after the debugging is that the symbol server that I was using had compressed symbols, and I needed to &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx"&gt;download and install a new dbghelp.dll and srmsrv.dll&lt;/a&gt; from Microsoft.  I still haven't been able to get it to download symbols to my local store from Microsoft and McNeel's public symbol servers in the profiler itself, but that's not a huge deal, as I can get VS2005 to download them for me, and very sleepy reads them just fine out of the symbol store.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-8729750664467831827?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/8729750664467831827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=8729750664467831827' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/8729750664467831827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/8729750664467831827'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2009/06/very-sleepy-profiler.html' title='Very Sleepy Profiler'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-9217569733107099116</id><published>2009-06-11T05:25:00.000-07:00</published><updated>2009-06-11T05:40:40.435-07:00</updated><title type='text'>"I'd just google it" as an interview answer</title><content type='html'>Recently read an &lt;a href="http://improvingsoftware.com/2009/05/15/why-id-just-google-it-is-not-an-acceptable-interview-answer/"&gt;interesting post about whether "I'd just google it" is an acceptible interview answer&lt;/a&gt;.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I agree that it's usually not a good idea as a final answer.  However, if the question &lt;i&gt;is&lt;/i&gt; something that I would just google, I'd probably say something like: "If I &lt;i&gt;actually&lt;/i&gt; had this problem, I'd probably research it on the internet.  However, assuming that I couldn't find anything, here's what I'd do...".  This way you show that you're practical, but you also answer the question as asked.  I've worked with people that were great at solving problems by themselves, but horrible at deciding when to use a library vs. when to do it themselves.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I gave an interview for a system admin at the graphics lab once.  For the technical part of the interview, I asked him what he would do if there was a server running redhat linux, which he had physical access to, but nobody remembered the root password.  He said he didn't know.  I pointed him to a nearby machine said that the question was open-internet, and left him to search.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;After a few minutes he came back and showed me that there were a few different approaches, explained their pros and cons, and in which order he'd try them.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;He made a great admin.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-9217569733107099116?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/9217569733107099116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=9217569733107099116' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/9217569733107099116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/9217569733107099116'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2009/06/id-just-google-it-as-interview-question.html' title='&quot;I&apos;d just google it&quot; as an interview answer'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-6850368957262265686</id><published>2008-11-18T08:43:00.000-08:00</published><updated>2008-11-18T08:48:56.088-08:00</updated><title type='text'>Keyboard use is overrated</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; white-space: pre-wrap; "&gt;&lt;div&gt;I was just reading &lt;a href="http://www.codinghorror.com/blog/archives/001188.html"&gt;a post on codinghorror&lt;/a&gt; about how good programmers should necessarily be good typists.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;I feel like maybe I should be submitting this to the daily WTF, but I knew a programmer who had a keyboard tray, and he kept his keyboard stowed.  While programming.&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; white-space: pre-wrap;"&gt;He was a VB programmer, and I guess it's somehow possible to program in VB using only your mouse.  I sat near him, but I never asked him how exactly he was able to do it.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; white-space: pre-wrap;"&gt;My guess is that he first laid out his UI, which auto-assigned names.  Double-clicking on elements allows event handlers to be created.  He also spent a lot of time in really long drop-down lists, so I'm guessing there was a list of functions, and a list of variables, and he was just filling in the blanks with selections from his list.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; white-space: pre-wrap;"&gt;Every once in a while he'd get stuck and have to pull out his keyboard to type something, but he was always annoyed about it.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-6850368957262265686?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/6850368957262265686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=6850368957262265686' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/6850368957262265686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/6850368957262265686'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2008/11/keyboard-use-is-overrated.html' title='Keyboard use is overrated'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-5088934296499045658</id><published>2008-07-19T21:03:00.000-07:00</published><updated>2008-07-19T21:24:48.666-07:00</updated><title type='text'>Build order</title><content type='html'>So, I do a lot of compiling at work.  The project is large enough that I think twice before modifying header files that would cause most of the project to rebuild, such as defs.h or point.h.&lt;br /&gt;&lt;br /&gt;One problem I have is that when I'm modifying such a file, compiling the project (F7) results in a complete recompile, to bring the project up to sync with the modified header.  This is a significant amount of effort, but necessary.&lt;br /&gt;&lt;br /&gt;However, sometimes I've made a mistake when making changes.  Sometimes I need to edit the header file again.  For example, maybe I've forgotten to make functions const that need to be const.  After finding the error, I need to fix it and re-start the compilation process.&lt;br /&gt;&lt;br /&gt;So, that's the problem.  Here's a proposed fix: rather than compiling all the files in a given project alphabetically, compile them from most recently edited to least recently edited.  There are a couple of places where an error would be detected, but it's more likely going to show up in a file I was recently editing, rather than one that was last touched 4 years ago, but starts with the letter A.&lt;br /&gt;&lt;br /&gt;I'm not even sure if this is possible to set up with the current tools, but why isn't this the default?  Is there a downside I'm not seeing?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-5088934296499045658?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/5088934296499045658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=5088934296499045658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/5088934296499045658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/5088934296499045658'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2008/07/build-order.html' title='Build order'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-4915821129657736533</id><published>2008-05-22T12:14:00.000-07:00</published><updated>2008-05-22T12:22:16.965-07:00</updated><title type='text'>Vista's UAC at work</title><content type='html'>So, most of my day-to-day programming is a plugin to a windows program. &lt;br /&gt;&lt;br /&gt;There are various build configurations that produce output, and as a post-build step, we run a silent installer that makes sure that the output of the current configuration is the one installed in the host app.&lt;br /&gt;&lt;br /&gt;This worked great until Vista.  With UAC, every time I finish a build, I have to click Allow for the installer.  This does not help my workflow.&lt;br /&gt;&lt;br /&gt;Perhaps the simplest solution is 'blessing' the installer executable with admin rights, so that it knows I trust it, similar to the SUID bit on unix/osx.  Apparently SUID was considered too dangerous for Vista, which I understand, given the amount of legacy software that would be insecurely ported in this way.&lt;br /&gt;&lt;br /&gt;The other solutions I can think of involve disabling UAC or installing XP, which sort of defeats the purpose.&lt;br /&gt;&lt;br /&gt;Anyone have any better ideas?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-4915821129657736533?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/4915821129657736533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=4915821129657736533' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/4915821129657736533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/4915821129657736533'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2008/05/vistas-uac-at-work.html' title='Vista&apos;s UAC at work'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-3691079066329423069</id><published>2008-03-18T12:53:00.000-07:00</published><updated>2008-03-18T13:08:11.820-07:00</updated><title type='text'>iPhone background processing</title><content type='html'>After reading Craig Hockenberry's post about &lt;a href="http://furbo.org/2008/03/18/more-brain-surgery/"&gt;background processes and notifications on the iPhone&lt;/a&gt;, I realized that there's one other option that's a possibility for dealing with background processes.&lt;br /&gt;&lt;br /&gt;Basically, you have an application like growl that centralizes notifications, and other things like network usage, etc.  Applications can register callbacks to the notification system, so that their background processes start when you run the notification app, when something is using the network they get notified, etc.&lt;br /&gt;&lt;br /&gt;I'd also build in a process manager.  And solitaire.  And a web browser.  Oh not.. :)&lt;br /&gt;&lt;br /&gt;This means that the user can decide when they want notification, how often they want the network to be used, etc.&lt;br /&gt;&lt;br /&gt;This would add complication and control, and is likely overkill for most users, but I can see how such a framework would be handy for a user with multiple applications that need to be running at the same time.  There's really no other way for multiple applications to run at the same time besides using a jailbroken iPhone.&lt;br /&gt;&lt;br /&gt;Whether the security model allows for it is another issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-3691079066329423069?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/3691079066329423069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=3691079066329423069' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/3691079066329423069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/3691079066329423069'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2008/03/iphone-background-processing.html' title='iPhone background processing'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-3338049240920123651</id><published>2008-03-15T20:04:00.000-07:00</published><updated>2008-03-15T20:40:09.105-07:00</updated><title type='text'>iPhone background apps, and laptop sleep</title><content type='html'>So, there has been some &lt;a href="http://daringfireball.net/2008/03/foot_meet_bullet"&gt;discussion on daring fireball&lt;/a&gt; about the iPhone and running background apps.&lt;br /&gt;&lt;br /&gt;There's not much reason to run background apps on the iPhone - it is essentially a single-tasking device.  There are some applications on the iPhone that run background apps, such as iTunes and file transfer.  However, you can still do most things, even tricky things like IM, completely as a foreground app.&lt;br /&gt;&lt;br /&gt;The trick is to use an intermediate server to buffer communications.  When the user is logged into an IM, the server logs in.  When the user switches to a different app, the server remains logged in, maybe switches status to 'away', and queues the messages.  When the user switches back to the app, it knows it was logged in, and downloads any queued messages.&lt;br /&gt;&lt;br /&gt;What would this prevent?  Well, it would prevent the app from popping up when an incoming message is received, which might be desirable anyway.  It would also prevent apps that need to continually send out data without being in the foreground.  Finally, apps that require a lot of computation would need the user to stay in the app while it computes, so no encoding video in the background on your iPhone.  While it's arguable that these applications should be possible, most of what people want to do can be accomplished by using an intermediate buffering server, or forcing the user to keep the app in the foreground.&lt;br /&gt;&lt;br /&gt;What are advantages of no background apps?  Well, if the iPhone has a security flaw, or even in the case of trojan programs, the user would be unaware if the iPhone became a zombie, and the user has none of the tools necessary to even notice such behavior, nevermind track it down.  There is no process viewer, and it goes against the single-tasking design of the device.&lt;br /&gt;&lt;br /&gt;Another issue that people have run into is the iPhone data problems while roaming.  Right now there is only one app that downloads data in the background, mail.  People have had problems in the past with mail massively running up their &lt;a href="http://www.nytimes.com/2007/09/10/technology/10iphone.html"&gt;roaming data bill&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The potential issues with battery life have already been discussed.&lt;br /&gt;&lt;br /&gt;I think Apple's stance on this is similar to their stance on sleep.  I've seen lots of people walking around with windows-based laptops open, going between classes or meetings.  All applications on windows are notified that windows is going to sleep soon.  Any application can cancel or delay the sleep request, and enough do that the feature is basically worthless on most PCs.&lt;br /&gt;&lt;br /&gt;Sure, there are certain applications that would legitimately fail if the machine went to sleep, and might have good reason to cancel sleep requests.  There are hacks on OSX that allow this kind of behavior, but it took a while for them to become available.  In the meantime, most apps were written to behave well under the default configuration.&lt;br /&gt;&lt;br /&gt;The end result is that when I close my mac, it goes to sleep.  When I open it back up, it comes back up.  It's fast, and it always works.  The common case works well, and the uncommon case works eventually.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-3338049240920123651?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/3338049240920123651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=3338049240920123651' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/3338049240920123651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/3338049240920123651'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2008/03/iphone-background-apps-and-laptop-sleep.html' title='iPhone background apps, and laptop sleep'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-2691628324264241007</id><published>2007-12-10T12:17:00.000-08:00</published><updated>2008-03-15T20:55:49.832-07:00</updated><title type='text'>Distributed tinyurl</title><content type='html'>TinyURL seems to suffer from a few problems:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Single point of failure&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.wordyard.com/2007/10/05/terror-of-tinyurl/"&gt;Not human readable&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Not reversible&lt;/li&gt;&lt;/ul&gt;How could you combat these problems?&lt;br /&gt;&lt;br /&gt;The goal is to have a large URL replaced by a small URL.  Simple compression or hashing of the URL &lt;a href="http://www.codinghorror.com/blog/archives/000935.html"&gt;isn't going to work&lt;/a&gt;.  You need to iterate through possible values, or the output will be unusually large.&lt;br /&gt;&lt;br /&gt;I normally come to solutions iteratively, and this one still feels half-baked.  But it's at least half-delicious.&lt;br /&gt;&lt;br /&gt;Standardize on a shortened URL scheme.  Each shortened URL is a small hash of the actual URL, plus a unique identifier.  Entries are propagated through a system of distributed hosts, and lookups can be achieved by querying the closest server.&lt;br /&gt;&lt;br /&gt;Standardization allows you to integrate functionality into webbrowsers and similar tools to lookup the URLs before clicking, and display the actual URL right where it's normally displayed.&lt;br /&gt;&lt;br /&gt;Distributed hosts allow you to avoid the single point of failure.&lt;br /&gt;&lt;br /&gt;And using the hash of the URL plus a unique identifier allows you to have confidence that your local server is returning a valid URL, and the correct URL.  If you use a hash that's cryptographically strong, you get cryptographic guarantees against tampering with the database. &lt;br /&gt;&lt;br /&gt;I'm not sure of any cryptographic-strength hashes that would work well on input data as small as URLs, or produce small enough output, so that's a potential problem.  Also, I imagine the sysadmins of the world wouldn't be keen on supporting another big distributed system, especially for such a trivial issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-2691628324264241007?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/2691628324264241007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=2691628324264241007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/2691628324264241007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/2691628324264241007'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2007/12/distributed-tinyurl.html' title='Distributed tinyurl'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-1669091170471812164</id><published>2007-11-14T09:24:00.000-08:00</published><updated>2007-11-14T12:44:35.122-08:00</updated><title type='text'>How much for a sanctioned custom iPhone ringtone?</title><content type='html'>After reading Daring Fireball's frequent posts on Apple's &lt;a href="http://daringfireball.net/2007/09/the_ringtones_racket"&gt;ringtone policies&lt;/a&gt;, I was curious about how much it would cost to get a custom ringtone on the phone. &lt;br /&gt;&lt;br /&gt;While there are various software hacks and workarounds to get ringtones on the phone, the only Apple-sanctioned method is to buy a song from the iTunes music store and convert it to a ringtone with their custom tool.  Because it's sanctioned by Apple, it's the only kind of ringtone you can be sure won't suddenly disappear after a software update.&lt;br /&gt;&lt;br /&gt;Unfortunately, there aren't too many clips of my daughter saying "ring, ring, ring" on the iTMS.  As you can imagine, I'm pretty attached to my ringtone.  If I ever scrape together enough money to buy an iPhone, it would have my ringtone on it, one way or another.&lt;br /&gt;&lt;br /&gt;For the Apple-sanctioned approach, the main trick is getting my track onto the iTunes store.  After some googling, I found that &lt;a href="http://cdbaby.net/dd-money"&gt;cdbaby will distribute tracks&lt;/a&gt; on the iTMS.&lt;br /&gt;&lt;br /&gt;The charges break down as follows:&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;$35    cdbaby cd fee&lt;br /&gt;$20    cd barcode&lt;br /&gt;$  1     Buy on iTunes&lt;br /&gt;$  1     Convert to Ringtone&lt;br /&gt;&lt;br /&gt;$57     Total&lt;/blockquote&gt;This is not completely accurate, because you'll also need to burn a CD and mail it to cdbaby, and you'll get some sort of payment back from cdbaby after you buy your own track. &lt;br /&gt;&lt;br /&gt;You could also reduce the costs by getting a bunch of people to go in on the same CD. &lt;br /&gt;&lt;br /&gt;However, it's pretty obvious that this isn't much of an alternative to the current hacks and workarounds to achieve the same thing for almost free.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-1669091170471812164?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/1669091170471812164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=1669091170471812164' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/1669091170471812164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/1669091170471812164'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2007/11/how-much-for-sanctioned-custom-iphone.html' title='How much for a sanctioned custom iPhone ringtone?'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6197006951470169345.post-2284152141066667817</id><published>2007-09-30T13:36:00.000-07:00</published><updated>2007-11-14T12:47:40.505-08:00</updated><title type='text'>Making Wrong Code Not Compile Either</title><content type='html'>Every once in a while I feel an impulse to write a longer response to something I read than the comments section of a blog will allow.&lt;br /&gt;&lt;br /&gt;Hopefully this blog will help me follow through on those impulses.&lt;br /&gt;&lt;br /&gt;In that spirit, Joel Spolsky wrote &lt;a href="http://www.joelonsoftware.com/articles/Wrong.html"&gt;an interesting defense of true Hungarian Notation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In general, I agree with the thesis: used properly, Hungarian Notation can make bad code look bad, and increase code quality in general.&lt;br /&gt;&lt;br /&gt;Hungarian in this case is simply used to encode meaning into the variable name. That's great - the variable name is a wonderful place to put descriptive information about what the variable is and how it's used.&lt;br /&gt;&lt;br /&gt;However, Joel's suggested problem and solution are sub-optimal, and he paints c++'s type system as a disaster compared to c.  While c++ can be used badly, the more flexible type system can be used to combat the same problems Joel is using Hungarian to solve, and more robustly.  Not that Hungarian is bad - what I'm saying is that there are a couple of different levels at which you can encourage proper usage, and the strongest is through proper typing.&lt;br /&gt;&lt;br /&gt;With c++ it's pretty easy to make bad code not only look bad, but not compile at all.  As a proof of this, I've written up Joel's safe/unsafe string example using c++.  You'll notice that I did include prefixes to my variable names in main.  You'll also notice that it would be very difficult for a programmer to use an unsafe string with a function that requires safe strings, and vice versa.  If I wanted to make it even harder to misuse, I could use some data hiding.&lt;br /&gt;&lt;br /&gt;The advantage of this strong checking is that a new programmer doesn't need to be trained to spot wrong code - the compiler will tell them when they do something bad.&lt;br /&gt;&lt;br /&gt;Without further ado, Joel's string example in c++.  This is the entirety of the file, designed for brevity.  It correctly compiles, but it will not compile either of the incorrect commands.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div    style=";font-family:Monospace;font-size:10pt;color:white;"&gt; &lt;span style="color:Blue;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div    style=";font-family:Monospace;font-size:10pt;color:white;"&gt;&lt;span style="color:Blue;"&gt;#include&lt;/span&gt;&lt;span style="color:Black;"&gt; &lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;&amp;lt;string&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Blue;"&gt;#include&lt;/span&gt;&lt;span style="color:Black;"&gt; &lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;&amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Blue;"&gt;using&lt;/span&gt;&lt;span style="color:Black;"&gt; &lt;/span&gt;&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt;&lt;span style="color:Black;"&gt; std;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Blue;"&gt;class&lt;/span&gt;&lt;span style="color:Black;"&gt; StringHolder&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Blue;"&gt;public&lt;/span&gt;&lt;span style="color:Black;"&gt;:&lt;br /&gt;  std::string str;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Blue;"&gt;class&lt;/span&gt;&lt;span style="color:Black;"&gt; UnsafeString : &lt;/span&gt;&lt;span style="color:Blue;"&gt;public&lt;/span&gt;&lt;span style="color:Black;"&gt; StringHolder {};&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Blue;"&gt;class&lt;/span&gt;&lt;span style="color:Black;"&gt; SafeString : &lt;/span&gt;&lt;span style="color:Blue;"&gt;public&lt;/span&gt;&lt;span style="color:Black;"&gt; StringHolder {};&lt;br /&gt;&lt;br /&gt;UnsafeString request()&lt;br /&gt;{&lt;br /&gt;  UnsafeString retval;&lt;br /&gt;  retval.str = string(&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;"This string is unsafe."&lt;/span&gt;&lt;span style="color:Black;"&gt;);&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:Blue;"&gt;return&lt;/span&gt;&lt;span style="color:Black;"&gt; retval;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;SafeString encode( &lt;/span&gt;&lt;span style="color:Blue;"&gt;const&lt;/span&gt;&lt;span style="color:Black;"&gt; UnsafeString&amp;amp; unsafe )&lt;br /&gt;{&lt;br /&gt;  string temp = unsafe.str;&lt;br /&gt;  string find_me( &lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;"unsafe"&lt;/span&gt;&lt;span style="color:Black;"&gt; ), replace_with( &lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;"safe"&lt;/span&gt;&lt;span style="color:Black;"&gt; );&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:Blue;"&gt;while&lt;/span&gt;&lt;span style="color:Black;"&gt; ( &lt;/span&gt;&lt;span style="color:Blue;"&gt;true&lt;/span&gt;&lt;span style="color:Black;"&gt; )&lt;br /&gt;  {&lt;br /&gt;      std::string::size_type pos = temp.find( find_me );&lt;br /&gt;      &lt;/span&gt;&lt;span style="color:Blue;"&gt;if&lt;/span&gt;&lt;span style="color:Black;"&gt; ( pos != string::npos )&lt;br /&gt;      {&lt;br /&gt;          temp.replace( pos, find_me.size(), replace_with );&lt;br /&gt;      }&lt;br /&gt;      &lt;/span&gt;&lt;span style="color:Blue;"&gt;else&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Black;"&gt;        {&lt;br /&gt;          &lt;/span&gt;&lt;span style="color:Blue;"&gt;break&lt;/span&gt;&lt;span style="color:Black;"&gt;;&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  SafeString retval;&lt;br /&gt;  retval.str = temp;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:Blue;"&gt;return&lt;/span&gt;&lt;span style="color:Black;"&gt; retval;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Blue;"&gt;void&lt;/span&gt;&lt;span style="color:Black;"&gt; write( &lt;/span&gt;&lt;span style="color:Blue;"&gt;const&lt;/span&gt;&lt;span style="color:Black;"&gt; SafeString&amp;amp; safe )&lt;br /&gt;{&lt;br /&gt;  cout &amp;lt;&amp;lt; safe.str &amp;lt;&amp;lt; endl;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&lt;span style="color:Black;"&gt; main( &lt;/span&gt;&lt;span style="color:Blue;"&gt;int&lt;/span&gt;&lt;span style="color:Black;"&gt;, &lt;/span&gt;&lt;span style="color:Blue;"&gt;char&lt;/span&gt;&lt;span style="color:Black;"&gt;** )&lt;br /&gt;{&lt;br /&gt;  UnsafeString us_input = request();&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:Green;"&gt;//write( us_input );  // Doesn't compile&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Black;"&gt;    SafeString s_output = encode( us_input );&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:Green;"&gt;//s_output = encode( s_output );  // Doesn't compile&lt;br /&gt;&lt;/span&gt;&lt;span style="color:Black;"&gt;    write( s_output );&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt; &lt;/span&gt;&lt;/div&gt; &lt;/blockquote&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6197006951470169345-2284152141066667817?l=tfinniga.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tfinniga.blogspot.com/feeds/2284152141066667817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6197006951470169345&amp;postID=2284152141066667817' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/2284152141066667817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6197006951470169345/posts/default/2284152141066667817'/><link rel='alternate' type='text/html' href='http://tfinniga.blogspot.com/2007/09/frist-psot.html' title='Making Wrong Code Not Compile Either'/><author><name>Tom Finnigan</name><uri>http://www.blogger.com/profile/01359351403251561655</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
