<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Don’t expect coherency, don’t expect an unbiased journalistic style blog, don’t expect me to be right, don’t expect me to be perfect. Simply stay if you like what you see.</description><title>Dinesh Harjani's thoughts</title><generator>Tumblr (3.0; @dinesharjani)</generator><link>http://dinesharjani.com/</link><item><title>Week 7 - The Unexpected Passenger</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/841d0d7a8fc257e9ffa02ab31776fea9/tumblr_inline_mn43s9CoCK1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Note that the &lt;a href="http://getpebble.com/"&gt;Pebble watch&lt;/a&gt; is not the &amp;#8220;Unexpected Passenger&amp;#8221; mentioned in this post&amp;#8217;s title)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I know I&amp;#8217;m late by a day, but I was busy until yesterday finishing the latest touches before wrapping up. It doesn&amp;#8217;t feel like it&amp;#8217;s my first update since I held off from programming a full 7 Days, mainly because after a day I was completely into it again, and because right now it feels as if I never stopped, and that I completely did the right thing back then.&lt;/p&gt;
&lt;p&gt;I have to warn you, though. There won&amp;#8217;t be many pictures to showcase this time, mainly because I didn&amp;#8217;t feel the need to draw a lot more, and because the project as it is right now is in an inconsistent state: the Engine is kind of disabled for timeframe refurbishments, so I can&amp;#8217;t run the new code, and even if I did there&amp;#8217;s nothing new to show. But some interesting work was done, and I can&amp;#8217;t wait to tell you all about it.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;On Monday we begin. My first order of business, as you know, was implementing a serial architecture for operations on the Standard Engine. I decided in the end this would not be a feature of the Zealot Engine design, so the SE had to keep the external methods required by the ZE Objective-C protocol, but run them asynchronously by using the Protocol methods as an Interface to the real methods which are wrapped in dispatch_async blocks. This did not present a problem for the main job of the Engine: refreshing the Track. As it was, we already architected this to work asynchronously with the ViewController receiving a Notification when the job was done. However, the Track filtering system did not work in this way: it was a synchronous method, you called it the moment you wanted the Track filtered and left with your response. This obviously needed to be changed, so I made Track filtering an integral part of how the Standard Engine works: you set how you want the Engine to filter the Track, and it keeps a filtered Track available at all times. When you need to change the filter setting, you do so and you&amp;#8217;ll get a Notification to update the Track. Naturally, whenever the Track itself is updated after a new Pool has been processed, the ViewController gets a newly filtered copy of it, true to the filter setting. This is important, because it will eventually allow the user to filter the Track by Supplier, so if you only want to watch Facebook content, you can do so and still refresh the Track. Or Twitter content. Or Tumblr content. Or whatever.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/2aa5bf6232ec6f5c1cf07160a860f85a/tumblr_inline_mn42zevy8i1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;This eventual feature was of curse inspired by Tweetbot and by Google+ for iOS&amp;#8217;s management of Circles, only this design will perform admirably quicker, because we already have all the information we need: it&amp;#8217;s just running through the Array, writing down the indexes of the Tickets the user wants, making a new Array out of them, and displaying them. No Network requests involved.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;With the Track issues solved, after making sure all current tests were still passing (even though I still need to revamp them for timeframes and so on, they were still useful to find out I hadn&amp;#8217;t broken anything I wasn&amp;#8217;t supposed to), I continued by transforming the Standard Engine so all of its available methods ran asynchronously. Once that was done, some tests wouldn&amp;#8217;t go through because in my testing I rely on a &amp;#8220;restart&amp;#8221; feature I crammed into the Engine which clears the Track and erases all previous information in the Suppliers (of course, this last task is handled by the Commander for the Engine, who knows who the Suppliers are and can deliver the message) so I could perform several small tests within the same &amp;#8220;test&amp;#8221; function. The trouble was I relied in the restart to be synchronous since the lines of code coming right after can be rendered useless by the restart if it doesn&amp;#8217;t happen exactly where I wanted it to, so the easiest solution bar turning the restart into a synchronous method (I did not because at least for debugging purposes I really want to have a &amp;#8220;Restart Engine&amp;#8221; button in my app) was to insert a &lt;strong&gt;sleep(1)&lt;/strong&gt; function. As it is, my tests do take time, so three or four seconds here and there doesn&amp;#8217;t hurt much.&lt;/p&gt;
&lt;p&gt;When I got it all running, I proceeded with some refactoring. Turning the Standard Engine into an asynchronous machine added more puff to its implementation, and it made me feel uncomfortable because I felt it was growing closer to the 1K-lines-of-code mark, with still a lot more features to cram in. To solve this, I looked no further than the Track class I&amp;#8217;d built a couple of weeks ago: &amp;#8220;isn&amp;#8217;t adding Tickets, or a Pool, a task a mutable Track would have to handle? And since this mutable Track is built specifically for the Standard Engine, is it wrong if this is the Class responsible for the Gap Detection &amp;amp; Gap Filling features?&amp;#8221; My conclusion was a sound &amp;#8220;no&amp;#8221;, so I spun off the appropriate code into a SEMutableTrack class, and the Engine became a lot cleaner and coherent. The filtering code also fell down to the SEMutableTrack, which is similar to how you can filter an NSMutableArray and get an NSArray with the indexes you want (in fact, that&amp;#8217;s exactly what I do). This opened my eyes to a very important issue regarding Objective-C: there are no protected properties. One thing I love to do is use Class extensions to &amp;#8220;hide&amp;#8221; my own instance variables from the outside, but this means that if I extend the Class, the Subclass can&amp;#8217;t access those ivars: there&amp;#8217;s simply no clean way. The Internet suggested I keep the ivars I want my Subclasses to see in a different header file used only by the implementation files, but three files per class seems a bit heavy for me, and it just doesn&amp;#8217;t explain why Objective-C won&amp;#8217;t allow you to share a property with a Subclass. I believe it&amp;#8217;s a very common theme in OOP, and it&amp;#8217;s also represents very big hole in Apple&amp;#8217;s premier programming language, which according to them, is the #1 programming language right now in usage stats.&lt;/p&gt;
&lt;p&gt;SEMutableTrack in hand, all tests successful, there was something else I wanted to go after before diving head-first into upgrading the SE to timeframes: I wanted a Pool class. My main idea was the following: studying Apple&amp;#8217;s concurrency guides, I understood better how the barrier I was using to control access to the Pool before being processed in the Engine actually worked. Putting a barrier in a concurrent queue means you have to &amp;#8220;wait&amp;#8221; until everything else in the queue finishes to get your exclusive access, which in real time performance could turn out to be stupid: it&amp;#8217;s simply time lost because when other Suppliers might not even be touching the Pool and are instead busy trying to fetch content off the Web we could be adding content to the Pool and freeing threads/memory. My solution to this was creating a Pool class which, similarly to how the SE now does, controls access to its most precious resource (an NSMutableArray) through a serial queue, only this time, calls would be synchronous. Now, synchronous calls can be dangerous if you&amp;#8217;re not careful and you call them on your own thread, but since this queue/thread will be invisible to everyone except the Pool instance, there shouldn&amp;#8217;t be issues of any kind; it&amp;#8217;s a pattern suggested in Apple&amp;#8217;s documentation, using serial queues to control access to your resources and get rid of barriers. I did not think doing so would allow me to get rid of the barrier itself, but I found a way of doing it. Getting rid of the barrier is tricky, because to do so the Pool itself needs to be responsible of telling the Supplier whether the Pool is already &amp;#8220;finished&amp;#8221; (i.e., all Suppliers have added their content to the Pool), and this should be done in a controlled way so no more than one Supplier goes down the &amp;#8220;finished&amp;#8221; or &amp;#8220;let&amp;#8217;s process the Pool&amp;#8221; code path (in other words, the critical section). I made the Pool good enough to know when all Suppliers have added their content to it in a very simple way: the Engine needs to register the Suppliers that&amp;#8217;ll pour in content into the Pool or else the Pool won&amp;#8217;t accept any Tickets from them. So, all Suppliers can pour in their content into the Pool, and then ask it whether it&amp;#8217;s complete or not. However, this question needs to be performed inside a barrier, or again, multiple Suppliers might get a &amp;#8216;YES&amp;#8217; answer, and still, I also need to control the critical section is executed only once, because the barrier code is executed right at the end, so more than one Supplier running that code might run into the Pool saying &amp;#8220;yes, everyone came in and left me their candy&amp;#8221;. It&amp;#8217;s still an improvement, because the Pool is filled out much faster, and the code inside the barrier is merely an &amp;#8216;if&amp;#8217;, but it could be done better, so I made the Pool itself answer whether it&amp;#8217;s completed or not when a Supplier fills it, and since this is done synchronously, only one Supplier is guaranteed to get &amp;#8216;YES&amp;#8217; as an answer, so a simple &amp;#8216;if&amp;#8217; without any barriers is enough to ensure the critical section is properly respected.&lt;/p&gt;
&lt;p&gt;Perfect.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/301aa345d481bbd837f37b043f48b7af/tumblr_inline_mn43vwKNaQ1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;All of that took until Tuesday night, and Wednesday turned into a bit of a slowdown.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I can&amp;#8217;t necessarily recall when exactly it was, but both Wednesday and Thursday ended up going a bit slow, and not much coding work took place. I believe I wrote down a few lines of code in paper to stretch out a basic wireframe of what I was going to do and how I was going to implement it, and ah!, now I remember, I found out, yet again, that I&amp;#8217;d almost missed another component: the two-dimensionality of the problem at hand. I was about to force Suppliers into the same realm the Standard Engine lives in, which is that Tickets should be delivered from [timestamp X] until [timestamp X-Y], but then it hit me: &amp;#8220;what if the Engine tried to process the Tickets of a Twitter user who has only published a single Tweet, and that too, back when the service was born in 2006?&amp;#8221; Aha! Suppliers needed to be limited too, so I inserted the timeThreshold: Facebook cannot possibly have content predating earlier than January 1st, 2004; Twitter since 2006, Tumblr since 2009, Instagram since 2010, Google+ since 2011, and so on. It might not seem decidedly elegant, but we can&amp;#8217;t just scroll backwards through time without a stop. Oh, wait! Can Facebook have content dating back to the 1900s after its new Profile debuted in late 2011? I guess it does… a much older timeThreshold for Facebook it is, then.&lt;/p&gt;
&lt;p&gt;Finding out I did not have everything figured out, I prompted myself to look into the future APIs I&amp;#8217;d be relying on to form my Suppliers (Facebook, Twitter, App.Net, Tumblr, …) and check if my Supplier API was adequate enough: the issue being I&amp;#8217;d been basing my timeframe idea on Facebook&amp;#8217;s own API, which &lt;a href="http://dinesharjani.com/post/48861231115/android-detour-facebook-newsfeed-sample"&gt;as I found out in my Android detour&lt;/a&gt;, allows you to set both upper and lower time limits to the content you&amp;#8217;re requesting. It turned out this API was mostly correct, only that most services required an ID as an anchor to follow on, not time. So for example if I want the Tweets coming after Tweet Z, I need Tweet Z&amp;#8217;s Twitter ID, not its timestamp. If my API worked giving you the key Ticket you were requesting Tickets after, everything seemed OK. Then a small idea hit me: these services are non-linear, I cannot expect them to provide me with Tickets starting from Tweet Z going all the way to the previous 5 minutes. For example, if I wanted to plug in an RSS feed as a Supplier, this would be a complete waste of time, because if I query an RSS feed, the first 5 items will be separated by a span of 3-4 hours at best, and my Engine might start querying the supplier for timespans of no more than 5 minutes: this is a huge waste of bandwidth!!! And the whole architecture would come down to a halt if this were the case. Even worse: if those RSS items are from 2-3 years ago, my Engine would take a good number of requests to get there (I have some kind of regression algorithm in mind to speed things up, don&amp;#8217;t worry), and it does not seem like a good design at all. &lt;/p&gt;
&lt;p&gt;On Thursday I dribbled a bit more to get my ideas sorted out, and eventually decided building a Cache was something I could definitely avoid, since for the moment I had Facebook and Twitter by my side, and a Cache subsystem might take me a full week to turn into reality.&lt;/p&gt;
&lt;p&gt;Friday morning was one of those big, big, big &amp;#8220;reality checks&amp;#8221;. It dawned on me I really was in trouble: a single Twitter request could give me Tweets from either the last 5 minutes or the last couple of hours/days, in any case, if in the first pass the Engine determines the Pool is not full enough and it can get some more content in, it&amp;#8217;ll end up asking the Twitter Supplier for more content: content it received in the first pass, but because there was no Cache in the middle, yet another network request would need to take place, unnecessarily.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/88c7385981000d47bf155aba9e800687/tumblr_inline_mn42vnwG0J1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Yes, I did. This Cache system is very, very, very necessary. So I got to work. If memory serves me right, principal coding (almost like in films!) starting on Saturday morning. I think I might&amp;#8217;ve scribbled something into Xcode on Friday evening/night, but the main ideas started to get laid down on Saturday. The main concept is the following: this Cache is non-existent for the Standard Engine. Whenever the SE requests Tickets in a timeframe to the Supplier, those requests are always fed by the Cache, so any content that&amp;#8217;s not on Cache needs to be fetched and added to it. This raises a question: &amp;#8220;Tweets and Facebook posts can be deleted at any time, what happens then? And how long does this Cache is supposed to last inside a Supplier?&amp;#8221; Tough questions. My choice was to leave whatever is published/posted in the Cache: if it gets caught by my app, it&amp;#8217;s not my fault. You decided to broadcast something to the world, and if you take it back, the risk&amp;#8217;s already taken, and it&amp;#8217;s not my fault if it ends up falling into the screens of my users. If those Tickets are at the top of the Track, a quick refresh might kill them off, (Top Filling algorithm will do them well), but if they&amp;#8217;re not, then they&amp;#8217;re not. We can figure out much later whether this is a bug, a *lack of features* or whatever, but in all honesty, the Web is as quick as a lightning bolt, and like many things IRL, sometimes you just can&amp;#8217;t take back what you just said. As for the second question, the Cache&amp;#8217;s sole purpose of existence is saving trips to the slow World Wide Web for my Suppliers, so it&amp;#8217;s cleared once the Pool has been completed and its contents are fully processed by the Engine. That&amp;#8217;s a change in the API I&amp;#8217;ll commit when I&amp;#8217;m done with the refurbishments.&lt;/p&gt;
&lt;p&gt;The basic way the Cache works is this: you query the Supplier for Tickets from X to X-5, the Supplier will ask the Cache if it covers said timeframe, and for the Supplier to do so, it needs to have content at least as recent as X&amp;#8217;s own timestamp, and at least one Ticket older than X-5, and the reasoning goes like this. When refreshing the Ticket, at say time XX, we cannot know whether all the Tickets we get from the Supplier stamped at time XX are all of them or not, because if we&amp;#8217;re at time XX, more content can be being added at every microsecond of XX up in the Cloud, so we cannot guarantee that; what we can guarantee though, is that we&amp;#8217;re covering a timeframe to a moment in the past, because we can ask for Tickets older than the one&amp;#8217;s we&amp;#8217;ve been requested, thus ensuring we are supplying exactly what we&amp;#8217;ve been asked for. If our last Ticket is stamped at precisely XX-5, it could be that said Ticket is truly the last one at that time, but we need to make sure, and for that, we need at least a Ticket stamped at XX-6 inside our Cache to make sure. This design supports a common theme in the Track: what&amp;#8217;s at the top might still belong there or might not. We don&amp;#8217;t know for sure, but what&amp;#8217;s below it does, because its anchored by what comes both before, and after.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/3242237e8ad808985e923b79e1663d3b/tumblr_inline_mn43usExCb1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;Back to how the Cache works: the Supplier asks its Cache whether it covers said timeframe or not. If it doesn&amp;#8217;t, a miss is triggered and the Supplier fetches content starting at the beginning of the timeframe (how much time these Tickets span is not up to us; that&amp;#8217;s the whole point!), which is then added to the Cache, and the question is repeated again: &amp;#8220;do you cover the timeframe requested by the Engine?&amp;#8221;. If the answer is yes, the Cache returns the desired Tickets in an Array, and we deliver them back to the Engine. If it&amp;#8217;s not, we fetch more Tickets starting at the oldest Ticket currently sitting in the Cache, and the cycle goes on. Simple. I also decided to limit the Cache&amp;#8217;s size, so what happens is every time new Tickets are fetched, if adding them to the Cache will make it surpass its maximum size, the Cache will clear out enough newest Tickets, and then they&amp;#8217;ll be added. As to why its newest Tickets, the premise is simple: the timeframe will move downwards in time, so if the Cache doesn&amp;#8217;t cover the timeframe, we need to add older Tickets, and chances are the newest ones are off the timeframe, so we don&amp;#8217;t need them, and can safely clear them out. If you&amp;#8217;re paying attention, you might&amp;#8217;ve already pointed out a slight problem in my thought process: I did not at the time, but eventually caught it.&lt;/p&gt;
&lt;p&gt;So, with this basic scheme for the Cache working, I set up tests between Saturday late night and Sunday morning: trigger an initial Cache miss, ask the Supplier for Tickets that don&amp;#8217;t trigger a miss, then force a miss by ending the timeframe the same second the last Ticket in the Cache is, space out the Tickets inside the Cache and test that a miss is not triggered… and then test the replacement (or eviction, as I called it) policy. This led me to an issue: if the Tickets covering the requested timeframe are more than what the Cache can hold at a single time, the design doesn&amp;#8217;t hold up, which is the issue I just mentioned at the end of the previous paragraph. The solution? Add any Tickets belonging to the timeframe that are already in the Cache before getting new ones if the Cache can&amp;#8217;t cover the timeframe all at once; after adding them, the timeframe to cover by the Cache is reduced until it fits in the Cache&amp;#8217;s maximum size, and we&amp;#8217;re done. An eventual &amp;#8220;Aggression test&amp;#8221; revealed another flaw in my design: &amp;#8220;what if the Supplier delivers more Tickets than can fit in the Cache during a single fetch?&amp;#8221; Actually, this is something very, very rare to happen IRL, since most APIs limit their delivery to 20-50 items maximum, so a Cache size of 30-60 should be more than safe. In any case, I wrote in a function that allows the Cache to grow in size as much as it needs just in case: for such a simple matter, it was pointless to be inflexible in the code. The Cache does have a maximum size to limit the amount of memory used, but it&amp;#8217;s not there to crash the program.&lt;/p&gt;
&lt;p&gt;That ends the full adventure for this past week. Unfortunately, from tomorrow onwards I need to work a bit on the Java and Android side, so I&amp;#8217;m not sure how much I&amp;#8217;ll be able to do about our project until next week. I&amp;#8217;ll try to give it a look, not leave it behind, and maybe start nailing down the code for the Engine to work in timeframes, but I&amp;#8217;m not really sure I&amp;#8217;m in a position to make promises for this week. For sure, I won&amp;#8217;t stop thinking about it: there&amp;#8217;s a lot of work to do still, because all the tests need to be revamped, but I&amp;#8217;m not losing hope. If we finish refurbishing the Engine, the light at the end of the pre-production tunnel will be so close, ending the journey would be like a walk through Champs-Élysées.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://media.tumblr.com/a645685afb05885292b28ccb4f61622c/tumblr_inline_mn4e51HhmN1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Picture by &lt;a href="http://www.flickr.com/photos/espinozr/4883375892/"&gt;espinozr@flickr&lt;/a&gt;. And no, that wasn&amp;#8217;t the picture I was originally looking for, but you&amp;#8217;ve got to admit it&amp;#8217;s got a pretty impressive feeling to it. So close&amp;#8230; yet so far away.)&lt;/em&gt;&lt;/p&gt;</description><link>http://dinesharjani.com/post/50943675135</link><guid>http://dinesharjani.com/post/50943675135</guid><pubDate>Mon, 20 May 2013 19:21:40 -0400</pubDate><category>personal</category><category>developers</category><category>development</category><category>ios</category><category>programming</category></item><item><title>Week 6 - Rest and No Relaxation</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/ab6acb8172cce69c505c73a54b02d013/tumblr_inline_mmp7mlqSOa1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Cover art by &lt;a href="http://mqken.deviantart.com/art/Zealot-263657151"&gt;mqken at DeviantArt&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Beginning to write this is getting harder than I thought, since &lt;span&gt;to keep my 17&amp;#8221; MBP comfortable to write (50-55 degrees Celsius) and without over-heating I&amp;#8217;m watching &lt;/span&gt;&lt;a href="https://www.youtube.com/watch?v=mvlZeZbNths"&gt;last week&amp;#8217;s episode of This Week in Tech&lt;/a&gt;&lt;span&gt; on my iPad next to me and thus getting the closest thing of an idea to what it is to have a pair of Google Glass on and above your eyes.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So, what was it for this week? I guess I sounded pretty down seven days ago, needing a big break or something. To be honest, by Monday I was already feeling the &amp;#8220;need&amp;#8221; to get to work, but I told myself that was precisely the reason why I had to stop for a few days. Then a couple more days went on, and I started feeling like maybe stopping was not a good idea, that it&amp;#8217;d get a bit hard to get back on the groove, but then I started really working towards the kind of problems I wanted to solve, and here I am with a big picture of what the Zealot Engine is missing.&lt;/p&gt;
&lt;p&gt;So yes, no code this week. I read &lt;a href="http://en.wikipedia.org/wiki/Enders_game"&gt;Ender&amp;#8217;s Game&lt;/a&gt;, and I also put my eyes through multiple WWDC sessions on Grand Central Dispatch plus a few Apple Developer Guides on Objective-C, Concurrency, OOP, etc. What we&amp;#8217;re going to do is quickly review again what was the main issue which brought me to a halt last week, and after that we&amp;#8217;ll cover the main four features I believe are missing from our Zealot Engine concept.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/410b32a751949882ab26ca6188e685a9/tumblr_inline_mmp7v8viKQ1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;Back to the &amp;#8220;timeframe&amp;#8221; issue. Going back to how we&amp;#8217;ve designed the Zealot Engine from the start, I&amp;#8217;ve been making a mistake right from the moment I started to write down the code. Why? Well, because until now, the Suppliers have been behaving too good: every time we&amp;#8217;ve been requesting for Tickets, they all deliver Tickets corresponding to the same timeframe. This means all the Tickets received are &amp;#8220;expected&amp;#8221; to start and end at a certain timestamp: something which obviously won&amp;#8217;t happen with a &amp;#8220;real&amp;#8221; supplier like say, Facebook. I can give you another example: imagine it&amp;#8217;s just a week and a half ago and I suddenly add a Supplier inputting Paul Miller&amp;#8217;s Tweets; I&amp;#8217;d be mixing content from today with the one coming 365 days ago, and because of how the Engine manages its Pool, all the Tickets in the Track would be utterly destroyed, because the Pool ends a full year ago, and if there were any content in between the Engine assumes (correctly) that the Pool would end closer to the top (newest Tickets) in the Track… you hopefully get the idea. That can&amp;#8217;t obviously happen: the Engine is the one responsible for handling this issue; it&amp;#8217;s its main job. Suppliers only need to worry about &amp;#8220;supplying&amp;#8221; Tickets, nothing else (for now, at least).&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/775cf0749f15d9fc0bae1a8b6743db06/tumblr_inline_mmp7ycCeNQ1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;Now, we&amp;#8217;ve decided we need to modify the Engine to work on the basis of &amp;#8220;timeframes&amp;#8221;. But I have a bigger question: &amp;#8220;who&amp;#8217;s to say this is the right design? What if I missed something else?&amp;#8221; It&amp;#8217;s a nice question. I went through as many examples as I could, since that&amp;#8217;s the only way I thought could find a new use case I hadn&amp;#8217;t accounted for before. Of course, it covers the issue I&amp;#8217;ve mentioned before, so that&amp;#8217;s solved. New question: &amp;#8220;how re-usable is the Engine&amp;#8217;s current design?&amp;#8221; Suppose I wanted to re-use the Engine to display only someone&amp;#8217;s tweets. Is that possible? Is it as simple as making a new Standard Engine instance and displaying its Track in an UITableView? Almost. If you&amp;#8217;ve been paying attention you should be able to figure it out. Ready? Well, the answer is a simple &amp;#8220;yes&amp;#8221;. You only need two things: one, you need a Supplier to give you those tweets (obvious), and two, you need to make your own Commander to install that Supplier into your Standard Engine instance, and boom! So yes, it&amp;#8217;s perfectly re-usable. This was always a design goal, but I never asked myself before whether the current design was good enough to meet it: it is. Next. &amp;#8220;Is the current pull-to-refresh-based design good enough? What if we want to go live-streaming?&amp;#8221; Well, it was never my intention to make the Zealot Engine support streaming; I wanted to solve the problem first and make it that much comfortable later. In case it did get good enough or I consider moving it to the Mac, then I could constantly be polling the web for new Tickets. Still, &amp;#8220;what if&amp;#8221;? Well in that case, the information would still need to come from the Suppliers, in the sense that the Suppliers would be constantly pushing information into the Engine. So internally, the Engine would need a couple of new hooks to talk to its Suppliers. Externally, we&amp;#8217;d probably need to enable or disable this feature someway, so maybe a new method for the API, too. But what I don&amp;#8217;t see is any need for API modifications: the current API would still need to exist, so the current design could be perfectly expanded to support live-streaming (we won&amp;#8217;t enter into how that could be possibly done), without altering any of the existing code using the Engine. That&amp;#8217;s also good news.&lt;/p&gt;
&lt;p&gt;So, if you wanted to know whether I&amp;#8217;ve found something else the Engine can&amp;#8217;t do, the answer is no. I might still be making a mistake, taking another big flaw along, but I think regarding the Standard Engine we&amp;#8217;re OK to at least get over the pre-production stage. What comes after that, we&amp;#8217;ll see when the time comes. Let&amp;#8217;s dive in.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/f7d4d3f3abb94d64142730b1634823ac/tumblr_inline_mmp7w6DDgo1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Before we begin talking about which features are missing, I&amp;#8217;m going to declare an answer to an un-answered question: &amp;#8220;how much exactly is the Standard Engine responsible for?&amp;#8221; It&amp;#8217;s obvious we&amp;#8217;re relying on it to provide us the feed of information, but how much more would we want it to do moving (theoretically) into production? I came with a very simple answer: if we look at a potential app from the point of view of screens, the Engine is responsible for the actions you can perform from the main timeline/feed screen. This involves both acquiring the feed, posting to the feeds, and setting a framework for the rest of the app to work on. Yes, I did say &amp;#8220;posting&amp;#8221;, but we&amp;#8217;ll leave that for later, not pre-production. And about that framework, we can set its foundations right now.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s our first order of business, actually. Not the &amp;#8220;timeframe&amp;#8221;. Before getting into that, we need to revamp how the Engine processes what we ask from it. What if in a production application, the user starts requesting a lot of different operations? For example: retweet, refresh and favourite. Or refresh, retweet, favourite and new post. What happens then? Can we do all at once? Well, we probably could, but there&amp;#8217;s something inherent (at least for me) in Social apps about posting something new and getting a confirmation saying your post was successful and at the same time seeing your own post in your feed, just like your friends will. This obviously needs to be controlled someway, and the idea I have in mind is some kind of serial queue processing each issued command to the Engine one at a time. So if you ask the Engine to do twenty different things, it&amp;#8217;ll do them, making sure the operations don&amp;#8217;t conflict with each other. (We&amp;#8217;re going to leave the GCD vs. NSOperationQueue discussion out of this one, or it&amp;#8217;ll be an even longer post.) To make things fully come around, we&amp;#8217;re going to make the Engine share this main command queue to its Suppliers, which&amp;#8217;ll be responsible for their own commands, and which I&amp;#8217;m not going to think about right now, but for which we&amp;#8217;re going to set the foundations now. You can also look at this command queue (haven&amp;#8217;t fully defined it yet; I call it the command queue following the Command Pattern which it closely resembles) as the queue to perform any kind of network operations through the Engine.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/a95bfaed7d98001ad238f852646dfe58/tumblr_inline_mmp7tmFcAP1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Moving on, we finally arrive to the timeframe part. This is the problem we&amp;#8217;ve discussed before, and I have some code layouts down on paper to make my mind clearer on how I&amp;#8217;m going to face this, but I can give you a simple idea: I&amp;#8217;m going to use two additional queues (again, not discussing whether I&amp;#8217;m going to use GCD or NSOperationQueues). The first one is the one we had before: a concurrent queue to allow each Supplier run at the same time. The second queue though, will be used to handle concurrent access to the Pool, which is the main contention problem we have while refreshing the Track. Instead of using a barrier as I&amp;#8217;ve done until now, it&amp;#8217;s much more efficient if I keep a serial queue to access the Pool, and it&amp;#8217;s also a lot faster. We&amp;#8217;ll discuss more about this as I resume my coding duties on the project. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Only the last two features of the Zealot Engine remain: the first I kind of haven&amp;#8217;t exactly figured out completely yet, and that&amp;#8217;s limiting the time each Supplier has to return with  Tickets. This is because I want to insulate the Engine from any failures going on in the Supplier side; say Twitter fails and due to my own coding mistakes the Supplier never returns back to the Engine. The Engine itself never finishes and thus the app becomes unusable? Not on my watch! The last element you already know of and there&amp;#8217;s barely not much thought in it: State Saving. Close the app, open it again: the content in front of you should be the same you had when you left. Not having State Saving puts the Engine through more varied situations than if if State Saving were implemented from the start, but that&amp;#8217;s honestly a good thing.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/76ffd5fa5333a5178677d313f2771b30/tumblr_inline_mmp7xg9atV1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;In-order architecture to process commands, in-Engine full &amp;#8220;timeframe&amp;#8221; support, built-in Supplier failure protection (yes, I&amp;#8217;m including protection against network issues too, here), and State Saving. They almost sound like features for a new Intel chip, but they&amp;#8217;re not. They&amp;#8217;re what separates the Zealot Engine and my own implementation of it, the Standard Engine, from being feature-complete, and thus concluding the pre-production phase of this project. I&amp;#8217;ll hopefully get back to full-time coding tomorrow, and if not after-tomorrow (little more design time). The next update in this blog should be a fairly standard one, with pictures of an app running and my cries and triumphs getting some new features (and their tests!) implemented.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Until then, make the most of the week, and if you&amp;#8217;re one of the lucky ones attending Google I/O, just don&amp;#8217;t miss many beats attending sessions and focus on the incredible people surrounding you.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;See you next week!&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;#8212; Epilogue &amp;#8212;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the time that&amp;#8217;s taken me write this post&amp;#8217;s first draft, edit it, transfer all the pictures to my Mac, sort through them, edit them, and write the final draft in the Tumblr console, I had a small but very important realisation: the reason why putting a &amp;#8220;full stop&amp;#8221; to my efforts was a pretty good idea is because I needed to get myself away from my own sense of failure. Getting Gap Technology to completely work turned into a daunting task for me due to that non-existent bug, and if&amp;#8217;d kept coding without taking a break after realising the huge flaw my design had, I&amp;#8217;d be carrying on me a weight that wasn&amp;#8217;t necessary; making mistakes is a big part of why I began doing this in the first place, and every lesson I learn makes me more valuable as a human being and as a professional, not the other way round.&lt;/p&gt;
&lt;p&gt;Again, thanks for following me in this little journey. And have a great week!&lt;/p&gt;</description><link>http://dinesharjani.com/post/50277202830</link><guid>http://dinesharjani.com/post/50277202830</guid><pubDate>Sun, 12 May 2013 14:48:11 -0400</pubDate><category>ios</category><category>programming</category><category>developers</category><category>development</category><category>personal</category></item><item><title>Week 3.5 to 5 - Gap Technology (Part II)</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/765badc5d189467e1adaf9314ba99348/tumblr_inline_mmag5feBhx1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;This is the week where I&amp;#8217;m going to admit to myself, and to you, that this little project has become a lot more than I thought it&amp;#8217;d be, because it&amp;#8217;s now a part of me. It no longer seems to be just &amp;#8220;an exercise&amp;#8221; or &amp;#8220;a prototype&amp;#8221;. It&amp;#8217;s my work now; part of what I am. A channel through which I&amp;#8217;m trying to give form to something entirely abstract (software) using what others judge to be &amp;#8220;my experience&amp;#8221;. Things got real this week, specially because I went through a hard time to get here, and it&amp;#8217;s tough to admit, because in practice, all the hard work was done two weeks ago, before the &amp;#8220;Android break&amp;#8221; we came to know as my Facebook Newsfeed (yeah, I know it&amp;#8217;s &amp;#8220;News Feed&amp;#8221;, but anyways) Sample code, and in reality it was too, but I crashed against a barrier that, as stupid as it sounds, didn&amp;#8217;t even exist to begin with.&lt;/span&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;We begin this 10-day odyssey last week&amp;#8217;s Friday, just after finishing the Sample code and giving myself a couple of hours to rejoice with my first public code in Github. The first thing I did was get to the table, open my notebook, get up to fill some ink into my fountain pain, and draw the problems I had to solve. As we discussed last week, I&amp;#8217;d actually done half of the work (if not more) surrounding Gap Technology because making Gap Detection I covered one Gap Filling scenario: syncing the Pool with the Tickets it had below the Gap (in the Track). Completing Gap Filling would be a matter of making some tests to make sure we could also &amp;#8220;extend&amp;#8221; the Gap at the end of the Track, make sure the Engine was capable of detecting that we&amp;#8217;d really run into the end of the Track (Suppliers did not have new Tickets that were older than the ones sitting at the bottom of the Track), plus a couple other cases. Before that though, we needed to solve a big UI problem, which is that so far the only communications with the Engine have been directly between the ViewController and the Engine itself. Filling in a Gap for example though, is very different, because the TableViewCell representing a Gap is not owned by the ViewController, but by the Engine through its Suppliers. How do we get the message from the Cell to the ViewController? I could&amp;#8217;ve done a lot of schemes involving delegates or causing all of the Ticket&amp;#8217;s interactions to channel towards a method in the ViewController (the didSelectRowAtIndexPath: selector), but in the end I opted for a very Objective-C like solution: notifications.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/223499bc3a74452630e52753df248136/tumblr_inline_mmag8vsOrn1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;By &amp;#8220;notifications&amp;#8221; I don&amp;#8217;t mean the ones you see on your Droid, iPhone, iPad or Mac, I mean the internal notifications used by Objects and libraries from the Cocoa Touch framework. Another similar solution would&amp;#8217;ve been using KVO or &amp;#8220;Key-Value-Observing&amp;#8221;, which is very similar in practical terms, but less straightforward. What you do in KVO is tell Cocoa you&amp;#8217;d like a selector (method for those who haven&amp;#8217;t done Obj-C) to be called when a property (member for those coming from Java) changes. I could&amp;#8217;ve used a special property just for triggering these kind of messages, but notifications seemed like a much cleaner and leaner solution. I also wanted the ViewController to control the action of what&amp;#8217;s done and what isn&amp;#8217;t at all times so, even though the UITableViewCell animates itself to show you&amp;#8217;ve &amp;#8220;activated&amp;#8221; a Gap, in truth it sends a message to whomever wants to listen to it, and the idea is that the ViewController will receive that message notification and then ask the Engine to &amp;#8220;fill in this Gap&amp;#8221;. That&amp;#8217;s the design I liked.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After going through all of that in paper, I spent Friday making that work, and since we were going to play a lot with time-based algorithms, I went ahead and made custom UITableViewCells for the ProgrammableSupply, showing an avatar, the user&amp;#8217;s name, the message and the Ticket&amp;#8217;s timestamp. Once that was working, I started to re-factor the code I had to Bottom-Fill a Gap so it could be re-used depending on an index. I re-ran all tests to make sure nothing was broken thus far.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/b2e5cb04d433ff1bc3a12e6ad3e5a48f/tumblr_inline_mmagbth7hH1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Saturday I started by testing. I made the code I had thus far &amp;#8220;extend&amp;#8221; the Gap we make at the end of the Track: that went without a hitch. Then I made a Standard Gap appear at the top of the Track, and filled it in normally, without triggering any new code, producing yet another Gap at the end of the new Pool. My idea was to test whether the Engine would be able to detect that the Tickets provided by the Suppliers did not cover the Gap we were filling in and to ensure a new Gap, covering less time, would be added at the right spot. This required some changes, since until then I&amp;#8217;d been adding Gaps directly to the Track, when in truth the correct way to do it is in the Pool. Why? Because the Tickets in the Pool are the ones guaranteed not to change, whereas the ones in the Track are at the mercy of whether they collide or not in time with the Pool (the &amp;#8220;Filling&amp;#8221; algorithms we&amp;#8217;ll talk about now). So I made that change, had all of the tests run, and all of it was working by Saturday evening. After coming back home from a very long walk and a nice dinner with a friend, I did not go to sleep: I came and I sat in front of the screen. If Gap Filling can be split into two distinct actions, which is taking care of the Tickets above the Pool (Top Filling) and those below it (Bottom Filling), the only thing I had left to do was the former one: so my idea was to take the test in which I&amp;#8217;d extended a normal Gap, and fill it with a bunch of recycled tickets to exercise the Top Filling code path. After two hours, I thought I got the code right, ran the test and saw it fail with strange numbers popping up in the Console Output. I told myself it was past 2am and I shouldn&amp;#8217;t expect to be in the best shape to be writing code, and decided it was probably something easy I&amp;#8217;d be able to fix on Sunday. (Spoiler alert! That was completely true, but it&amp;#8217;s not what happened).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Throughout Friday and Saturday I was taking the whole thing slowly: I knew it was only a matter of fixing some small chunks of code and making those tests to get it all done. I just needed to think clearly, go slowly, and get things done. So on Sunday I started looking at that &amp;#8220;Top Filling&amp;#8221; code, figured I had some mistakes here and there with the indexes, changed them, saw how the tests worked suddenly after shutting everything off except  what I was trying to fix, then turned the other tests on, and saw how they failed yet again. More changes, this time reverting back to what I&amp;#8217;d done before, and then everything worked, except Top Filling. So I turned all the other tests off except the first two: the first one produced a normal Gap and &amp;#8220;extended&amp;#8221; it, and the second (Top) filled it. The second one still failed, so I figured my problem was somewhere here. Again, after dinner I decided to give it another shot, and began looking closely at the Simulator, and that&amp;#8217;s when things started to go really wrong: it seemed like the algorithm wasn&amp;#8217;t working well on the second test not because it wasn&amp;#8217;t right, but because the pointer was getting assigned to the wrong Ticket even though its index was right. I went to bed on an absolute low point with a couple of horrible words stinging my mind: memory corruption.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/7d2b953037366687f9934e7d3e35db91/tumblr_inline_mmagajKKJU1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Somewhere, somehow, my first test was doing something it shouldn&amp;#8217;t have been doing because the second one did not correctly dereference an index from the Track: it used a wrong Ticket, and thus the algorithm wasn&amp;#8217;t working. There were no memory access errors of any kind; no exceptions, and like all memory problems, if I started turning on/off other tests the results started getting completely wild. Suddenly my threads stopped in a Block because they&amp;#8217;d lost ALL of their pointers, which led me to believe that maybe because I was passing in blocks as arguments many times and blocks didn&amp;#8217;t live on the heap but in the stack, somehow they were being deallocated before time. Yes, it started to get very, very &amp;#8220;Wild Wild West&amp;#8221; out here. I mean, I cannot explain it to you in words, but I really started to throw a lot of hours at this: like 6-7 or perhaps even 8 in front of the screen, plus more when I was not in front of the screen trying to tackle the problem. I began to realise Xcode was showing a lot of 0x00000000 or nil pointers in the Track after &amp;#8220;extending&amp;#8221; the Gap, which confirmed to me that something was going awfully wrong because all of those were strong pointers to my Tickets, and I believed inserting new Tickets was working all right, so no wonder my algorithm was failing because it must be accessing a corrupted section of memory or something. On Tuesday I ran Instruments and activated every single memory detection checkbox there is in Xcode, and nothing came clean. Nothing. To run Instruments well, I even made the same thing happen in the Simulator to get a reading on memory leaks, but there were no leaks except a few KiloBytes which I thought would most likely be auto-released NSStrings: the Tickets should leak more memory. Adding insult to injury, Xcode started to crash, too, just where you would guess: executing the Top Filling algorithm, at the precise line where I can check through the instance variable&amp;#8217;s memory addresses whether the Ticket was assigned correctly or not.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Despair seemed to be within my grasp.&lt;/p&gt;
&lt;p&gt;Wednesday I tried to focus on thinking differently: revising documentation about ARC, memory management, about GCD blocks being released prematurely, about array assignments being set incorrectly: the latter three did not have any results on Google. It briefly crossed my mind that maybe, since Top Filling was only triggered when the Suppliers were recycling Tickets (adding Tickets from the previous Pool into the new one) and that disabling recycling made everything work, that perhaps the error was somewhere lying in there. I gave it a look, and went a bit crazy doing hard-copies of the Tickets: I thought maybe they were being de-alloc&amp;#8217;ed because ARC wasn&amp;#8217;t holding on to them after the Suppliers stopped keeping them for recycling due to some ridiculous pointer referencing cycle (thus, why so many pointers were zero&amp;#8217;ed out). That didn&amp;#8217;t explain why the whole system worked in all of my previous tests, but who knew? That didn&amp;#8217;t work, so I looked at when and how the Track inside the Standard Engine was getting filled with zeros: it was after the Pool was being inserted in place. Previously, I&amp;#8217;d always been adding the Pool right at the end, but this was no longer possible since the Engine supported filling in Gaps, so it looked like this code was somehow responsible for at least some of the errors, even though I made it following Apple&amp;#8217;s own documentation. I changed it a couple of times, and in the last one I even built a whole new NSMutableArray composed of the Pool and the previous Track to form the new one, and voilá: Xcode showed the right results!&lt;/p&gt;
&lt;p&gt;Wait. Wait. Was Xcode playing with me all of this time?&lt;/p&gt;
&lt;p&gt;&lt;img src="http://media.tumblr.com/2e7bc81ed09b1bd796270875c56c1615/tumblr_inline_mmagfrn2aZ1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;It was. I realised that when after re-running the algorithm it turned the exact same results as before: the algorithm had always been working and there&amp;#8217;d never been any memory corruptions or leaks. My blocks were being dropped inside GCD because by mixing code I was telling the Engine to fill in at a non-Gap position: something it was not designed to do. (I admit to not following why exactly that was happening, but it wasn&amp;#8217;t the Engine had to do: that&amp;#8217;s why we came up with Gaps to begin with.) And the algorithm was not working because… guess why? The recycling code had a bug! I added new stuff to the Programmable Supply so it could either recycle the newest or the oldest Tickets from the previous Pool, and since from one Pool to the other you don&amp;#8217;t know which Tickets are going to be recycled and which aren&amp;#8217;t, the Tickets in the recycling Pool inside the Suppliers were out of order! That&amp;#8217;s why the Test failed depending on what was done before: because the Suppliers weren&amp;#8217;t recycling well. I added the same ordering code the Engine uses (3 lines), and… care to believe it? It worked!!!!!!&lt;/p&gt;
&lt;p&gt;What a great way to end Wednesday night. It was all solved: Top Filling worked, Bottom Filling worked. Now all that remained was putting up some tests for filling in a Standard Gap and we were done!! The single most-complicated feature of my Standard Engine had been solved!!!&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s where true happiness ends, though. I finished everything by Friday night. I took it all slowly, made sure it all worked, even made a couple of extra tests to handle a few difficult situations, but on Wednesday night, after walking my dog out just before heading to bed, I realised my Zealot Engine&amp;#8217;s concept and API was heavily, heavily flawed.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/96605605b325c00eb6eb353dec805b64/tumblr_inline_mmagcfkX4N1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;This is the same thing that did not allow me to solve Gap Detection quickly: thinking in only one or two dimensions. Consider this: the Engine is asking its Suppliers for Tickets. They deliver, and the Engine forms gaps if the timings don&amp;#8217;t match. However, I&amp;#8217;ve been relying on how all of this works in my perfect little world, not in the real world of different services and many, many users. The thing is: if I ask Facebook and Twitter to tell me what my friends might&amp;#8217;ve posted recently, Facebook might have 180 items from the last 20 hours, whereas Twitter might have 180 items from the last 20 minutes. This is not right, because the Engine will form a timeframe lasting twenty hours, when in reality many Tweets are clearly missing.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;This is a very big flaw: I could&amp;#8217;ve decided the Engine is not responsible for this and that the Suppliers should control the timeframes every Pool represents, but that&amp;#8217;s just nuts and stupid: it means making a lot of code that won&amp;#8217;t work when simply placing that code in the Engine would make the system work perfectly. This is an issue that leads to all sorts of problems, and the truth is, if you are building a Social Media app or an engine that only works with one source, you don&amp;#8217;t have to deal with this, because the timings are be enforced by the content you receive, not by your business logic. I messed this up the day I began this project: I messed this up the very same day on Week 2 when I drew all the interactions and didn&amp;#8217;t stop to think about this. I&amp;#8217;ve been putting a wrong foot ahead of another ever since Day 1 of Week 2.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img src="http://media.tumblr.com/17fe05b6763919c031c6cbbc99ca19a8/tumblr_inline_mmagh9aJsK1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s a big blow, because it&amp;#8217;s time I&amp;#8217;ve lost in this due to my own fault. And after Gap Technology, the remaining features are actually not that hard: State-Saving and protecting/preparing the Engine for Internet connectivity and unresponsive Suppliers. Had I taken my time, I wouldn&amp;#8217;t have to re-work the whole API and re-write each and every one of my tests so far. My goal of finishing the Standard Engine in this month of May now seems farther away, since I honestly don&amp;#8217;t know how long I&amp;#8217;m going to take re-designing the API to work on timeframes. You could come to me and say: &amp;#8220;Duuuuude, just refactor the hell out of it and be done at the end of a day!&amp;#8221; Yes, that&amp;#8217;d be the spirit. But I messed up once and don&amp;#8217;t want to mess up again. I&amp;#8217;m really going to take it slow now. I need a couple of days doing nothing, and by &amp;#8220;nothing&amp;#8221; I mean no code and no fountain pen for schematics. When I feel OK I&amp;#8217;ll start looking into a couple of apps, see if there&amp;#8217;s something else I might be missing, come back, get to the drawing board, fix the Zealot Engine, and then proceed refurbishing this ship.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://media.tumblr.com/15e676d64ff79fe34c6ca2ed0b757bfb/tumblr_inline_mmaghr7hAc1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;So that&amp;#8217;s what&amp;#8217;s ahead. I don&amp;#8217;t know how much work you should expect from me this week, because I don&amp;#8217;t have expectations from myself. I need a little bit of perspective, just a little bit, because this is just too close to my chest right now. I&amp;#8217;ll get back to work as soon as I can; I&amp;#8217;m not abandoning this, I promise. But I am sorry for letting myself and you down if you&amp;#8217;ve been following my progress thus far.&lt;/p&gt;
&lt;p&gt;Enjoy your weekend. Because, I&amp;#8217;ll be back.&lt;/p&gt;</description><link>http://dinesharjani.com/post/49614862581</link><guid>http://dinesharjani.com/post/49614862581</guid><pubDate>Sat, 04 May 2013 15:23:50 -0400</pubDate><category>personal</category><category>developers</category><category>development</category><category>ios</category><category>programming</category></item><item><title>Android Detour: Facebook Newsfeed Sample</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/f09908d82487e0755ff57e836e349c5f/tumblr_inline_mltjanuGLk1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Right, so last Sunday I mentioned I&amp;#8217;d be spending a few days doing Android code instead of following up with our project. I look forward to actually get going as soon as possible, so before that, I thought it&amp;#8217;d be a good idea to write a bit about my first ever piece of open source code on the web.&lt;/p&gt;
&lt;p&gt;The issue prompting me to  write this code is that many companies like to see some code before they trust you enough to sign you or even for an interview: they want to know how good you are, and if you don&amp;#8217;t have apps out there and you call yourself an &amp;#8220;Android &amp;amp; iOS Developer with 3-year experience&amp;#8221;, well, you&amp;#8217;ve got to back it up with something. I&amp;#8217;m not going to lie: I didn&amp;#8217;t want to lose focus on what we were doing, but I took the chance to do something I hadn&amp;#8217;t done since a very long time, which was working with Facebook&amp;#8217;s API.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/db20e543edeaddc5cfe3ef8997175222/tumblr_inline_mltloluauX1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;The idea for building a Newsfeed sample code on Android was pretty straightforward, since it was the closest thing I had to what I&amp;#8217;m currently working on and it&amp;#8217;s also the best opportunity I have to get some prior experience with &lt;a href="https://developers.facebook.com/docs/reference/api/"&gt;Facebook&amp;#8217;s Graph API&lt;/a&gt; before the day I (hopefully) have to call it down on iOS. I was a bit scared, though: I thought I&amp;#8217;d take a lot longer. I had no idea of how long it&amp;#8217;d take: in my best guesses I&amp;#8217;d be writing this text on Friday morning, not Thursday evening. Starting on Monday, I took it easy: spent some time on the web, started revising some Android code, some Android books, and started by opening up &lt;a href="http://www.jetbrains.com/idea/"&gt;IntelliJ-Idea&lt;/a&gt; and wiping out some code for an Android app that worked both on the old Android and the new one. &lt;a href="https://cursopudeandroid.googlecode.com/files/Ejercicio%20Intermedio%20A%20-%20Introducci%C3%B3n%20a%20Android%204.0%20Ed.%20Diciembre%202012.pdf"&gt;Something I&amp;#8217;ve kind of done before, of course&lt;/a&gt;. Then I realised the first thing I had to do was dive into the &lt;a href="https://developers.facebook.com/"&gt;Facebook Documentation&lt;/a&gt;, so I did.&lt;/p&gt;
&lt;p&gt;In the past, things like the &lt;a href="https://dev.twitter.com/docs"&gt;Twitter&lt;/a&gt; and Facebook Documentations seemed incredibly daunting to me; I mean, they&amp;#8217;ve got everything you might want to know, but they don&amp;#8217;t set you on a path, they just throw you into the Ocean and expect you to find the way towards what you&amp;#8217;re really looking for. Which is fine, if you exactly what you&amp;#8217;re looking for. Fortunately there are some tutorials and sample code here and there, but they&amp;#8217;re a bit sparsed throughout their sites. As always, &amp;#8220;the code doesn&amp;#8217;t lie&amp;#8221;, so going through Facebook&amp;#8217;s sample code for Android made me realise these folks have actually done a ton of work: not only for users of the Facebook API, but for any Android developer in general who&amp;#8217;s willing to take the little bit of time it takes to grab a part of the SDK and adapt it for their uses.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/b39a4d74fcc672d6ca45de67caa0b79f/tumblr_inline_mltln4jen61qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Tuesday morning, realising this was going to be a Github project, I started anew in a folder containing the Facebook SDK and the project itself. I started by what you&amp;#8217;d expect: logging in and showing my Profile picture. Once I got it running, I shifted the code a bit to specifically use an API Request to do that instead of relying on the LoginButton, and when that was done, it was time for the big show: downloading the Newsfeed.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I looked through the Documentation: no specific information about how to get my Newsfeed. No help on the web also. Looking into the SDK&amp;#8217;s methods I found I could make specific Graph API Requests, and having played with the &lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;a href="https://developers.facebook.com/tools/explorer"&gt;Graph Explorer&lt;/a&gt;&lt;span&gt;, I already knew exactly which address and with which parameters I had to work with. A little step here, though: I was writing everything into the address without taking care of URL encoding. Finally some code snippet I found around the WWW led me to introducing the parameters as a Bundle, and voila! Facebook started giving me my Newsfeed in JSON format.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But the app was crashing. The one thing I knew would be a bit tedious to code was JSON, because as much as I&amp;#8217;d rather work with JSON than with XML, JSON still requires a ton of boring old code to work with. Facebook apparently solved this: they automatically generate a Java Object strongly typed against JSON Object&amp;#8217;s parameters through a Java Interface. In other words: all you&amp;#8217;ve got to do is give a magic Object an Interface through which you want to access a JSON Object&amp;#8217;s properties, and from thereon, you can treat all the Java Objects as if though they implement that Interface. The Documentation mixes it up a bit when referring to &amp;#8220;Classes&amp;#8221; and &amp;#8220;Interfaces&amp;#8221; but ultimately I got it right, after finding out they made a mistake: the &amp;#8220;id&amp;#8221; property requires a getID() method, not a getId(). What do I mean? Well, to &amp;#8220;generate&amp;#8221; that code, Facebook relies on the names of the getters you specify in that Interface: it&amp;#8217;s all what you&amp;#8217;d expect it to be, really. The &amp;#8220;name&amp;#8221; property is &amp;#8220;getName()&amp;#8221; method, &amp;#8220;description&amp;#8221; is &amp;#8220;getDescription()&amp;#8221;, and so on. The only exception is the aforementioned &amp;#8220;id&amp;#8221;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/0b6da8ad24674080e3eb9bbe3d701b5b/tumblr_inline_mltlm3eLhF1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Once that was solved, I learned that I could also &amp;#8220;chain&amp;#8221; these so called Java proxies, in case a JSON Object had another Object as a property, which is nothing sort of wonderful. Wednesday was the day I brought all of this together to form a real working sample code, complete with a fancy looking row, an Adapter, a Wrapper or &amp;#8220;ViewHolder&amp;#8221;, and an AsyncTask to query Facebook for the Newsfeed. Because I never have enough, and because I&amp;#8217;ve always wanted to do it, I used an as-of-3-months new member of the Google Family&amp;#8217;s Pull-to-Refresh implementation and made it work to refresh. I used some of the experience from the project we&amp;#8217;ve been working on to get it all working just as we expect: new items at the top, and so on. There was no need for any fancy &lt;/span&gt;&lt;a href="http://dinesharjani.com/post/48561548010/week-3-gap-technology-part-1"&gt;Gap Detection code&lt;/a&gt;&lt;span&gt;, since all I had to do was to ask Facebook if there were any new Newsfeed Items since the last one we received (if only I were so easy on myself…), and no issues. We order the items, keep them always from oldest to newest, and the Adapter takes care of inverting how we see the items to form an ideal experience. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/bde732090c3a1e6bd69f758f0a9d2ea2/tumblr_inline_mltlgnuqC61qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;That was pretty much the full story. After that I added an option to Logout, since the Facebook Documentation begins by Login and Logout, and spent the rest of the time documenting and commenting all of the code. You can get it right &lt;a href="https://github.com/the7thgoldrunner/FacebookNewsfeedSample-Android/"&gt;here&lt;/a&gt;. And as always, I welcome any suggestions, comments or additions you may have :)&lt;/span&gt;&lt;/p&gt;</description><link>http://dinesharjani.com/post/48861231115</link><guid>http://dinesharjani.com/post/48861231115</guid><pubDate>Thu, 25 Apr 2013 12:57:00 -0400</pubDate><category>android</category><category>programming</category><category>developers</category><category>facebook</category><category>development</category></item><item><title>Week 3 - Gap Technology (Part 1)</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/4d01a7c3cd7d40a1142eb9201dfc84d2/tumblr_inline_mlm43hxhrb1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Sunday. I&amp;#8217;m back, and it&amp;#8217;s honestly been a long week for me. I had a lot of fun doing this, and I seriously thought I would either not hit my goals or not dodo as much work as I wanted to. For the first time in the last 21 days, I failed my own expectations, but given how complicated everything came out to be, I&amp;#8217;m really really glad about how things ended.&lt;/p&gt;
&lt;p&gt;Are you ready? This might get long again. Just to be sure, I won&amp;#8217;t be writing this in the Tumblr site itself but using iA Writer for the Mac :)&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Let&amp;#8217;s begin. On Monday, after finishing Part Two, I needed a rest. That meant watching a little bit of TV, specifically Game of Thrones (thrilling episode, although nothing important happened except a baby boy was born) to rejuvenate a bit, and then going back to coding right after dinner. Now, I don&amp;#8217;t know if I&amp;#8217;ve mentioned this before, but the requirements of the Zealot Engine are marked by what I consider the best social apps in the business, most prominently Tweetbot for iPhone. If this ever turns into an app I won&amp;#8217;t make it into a Tweetbot clone, but I want it to stand pretty close in terms of quality and features. One such feature I like from both Tweetbot and other great iOS apps such as Google&amp;#8217;s own Google+ client is the ability to &amp;#8220;switch timelines&amp;#8221;, and by this I mean (if we consider the Timeline to be the list of items you scroll through on the screen) that you can choose to see as much information as you can get (your full stream on both Twitter and Google+ respectively) or restrict it down to only some specific sources (lists and circles respectively again). This was a feature I did not remember about during the work period in Week 2, but it was clear to me over the following weekend, so it became first order of business in Week 3, and so I pursued it.&lt;/p&gt;
&lt;p&gt;The code itself was pretty simple: you can still ask the Engine for its full list of tickets, or you can ask for the list of Tickets filtered through a source. This is where the ZE implementation starts to get tricky, because no matter how &amp;#8220;abstract&amp;#8221; everything is coded, it&amp;#8217;s inevitable that at some point in development you&amp;#8217;ll have to write some code that knows about class specifics and/or is tightly coupled. If you don&amp;#8217;t, nothing will ever work. In this case, I decided to go for enums, so the Supplier protocol itself defines an enum with possible sources, [the enum] itself defined as an NSInteger with different values. What this means is that if somebody else wanted to use the Zealot Engine, they&amp;#8217;d either have to add their own enum values or change the ones I&amp;#8217;m using. If there is ever more than one &amp;#8220;Zealot Engine&amp;#8221; and it&amp;#8217;s not made by me, I think it&amp;#8217;d be OK if they used their own sources with different values. It&amp;#8217;s a Java-like approach, but for the scope of the work I&amp;#8217;m doing there shouldn&amp;#8217;t be any problems. If you&amp;#8217;re asking why this has arisen now, it&amp;#8217;s because when performing filtering over the Engine&amp;#8217;s current list of Tickets I had to filter using some kind of specific information, and the other idea I had was using specific classes for each Ticket. That seemed a bit messy for me, so clean and classic &amp;#8220;const&amp;#8221; strategy (enums in this case) it was. The code itself was pretty straightforward: when asked to deliver a filtered list I used an NSIndexSet and used the &amp;#8220;indexesOfObjectsPassingTest&amp;#8221; method to perform the magic. Pretty simple to write, and pretty simple to test. I did all of this on Monday night.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/05c8ad7eb97a0934783aa491677b62f6/tumblr_inline_mlmd9qJb4S1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Image found &lt;a href="http://teddybeartales.wordpress.com/2011/03/06/living-nostalgicly/"&gt;here&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On to Tuesday, but before we get to that, I&amp;#8217;m going to add a new name to our current mix of Tickets, Users, Suppliers, Engine(s), Pools and Commander(s): the Track. The concept of the Track became pretty clear to me at the beginning of this week, but I did not implement it until yesterday night past midnight (which is technically today only 17 hours ago), and what it is, is an abstracted look into the Tickets currently being held by the Engine, but much closer to the UI than to the Model. The Track itself is a concept: the &amp;#8220;list&amp;#8221; of tickets being held by the Engine, but I defined it as a class which is the one Engines communicate with, not NSArrays. This means nobody knows outside of the Track that what it really does is invert how you read the Tickets off of it, so that functionality is now performed by the Track itself, not by the ViewController making use of our Engine. This is actually something I should&amp;#8217;ve done since the beginning, but I&amp;#8217;m happy to have figured it out pretty quickly and to have performed this refactoring during this week.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;As to why it&amp;#8217;s called a &amp;#8220;Track&amp;#8221;, it&amp;#8217;s because if you can picture the sides of an iPhone&amp;#8217;s screen as the rails through which the Tickets keep on coming, the Tickets themselves look like the wood a railroad track is made out of in a classic &amp;#8220;railroad shot&amp;#8221;. To review the full Architecture a little bit, the Engine keeps the Track, builds a new Pool of Tickets, and when the Tickets forming the Pool are ready, they become a part of the Track. Onto the real meat of this week now.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Like I&amp;#8217;ve said, many of the Zealot Engine&amp;#8217;s features are demanded by what I think any user would expect from a well-crafted application. One of the most lauded features of Tweetbot in any of its variants (iPhone, iPad and/or Mac), is the way it keeps track of your Twitter Timeline throughout your use of it. Specifically, it has a way of representing all of the tweets in your Timeline in a very simple way to understand: gaps. Tweetbot adds gaps to your Timeline to let you know there are more tweets between the one above and the one below, and that you can see them if you so decide (by tapping on the gap), and there&amp;#8217;s also a gap at the end of your Timeline so you can keep scrolling down through your Timeline infinitely. Out of all of the functionalities the Standard Engine must have in the list, because this is specific to my implementation of my own Zealot Engine family of protocols, this has to be at the top in the complexity list. My thoughts on this were simple: filtering and Gap Technology. Surely they can be done this week?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/66ad43812fab46b85b615742840ac069/tumblr_inline_mlmkmsL2531qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Back to Tuesday. I already knew I wanted to tackle the &amp;#8220;Gap Technology&amp;#8221; feature head-on, so my first homework was implementing some way of detecting when two Tickets are the same. By &amp;#8220;the same&amp;#8221; I don&amp;#8217;t mean that they&amp;#8217;re the same Object, but that they represent the same information, which is likely to happen when updating the Track. To make it happen in a very straightforward way, I had to take another step forwards: the StandardTicket. Designed as the simplest unit of concrete information flowing through a Standard Engine, the StandardTicket properly implements the isEquals() method for any possible subclasses to make use of, plus a couple of improved setter methods here and there. Making the tests for this new functionality took me some time, and I lost Tuesday to this apparently tiny little thing. Gladly, everything was working by Tuesday night.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Wednesday. My head is beginning to hurt only by thinking about everything that started here. So, Wednesday there was no code. Actually Tuesday and Wednesday were both days in which I barely had any time to invest here, and I actually thought it&amp;#8217;d be a pretty horrible week; it wasn&amp;#8217;t in that sense. So, what I did on the while I had on Wednesday was pretty much sketch out everything related to what I defined &amp;#8220;Gap Technology&amp;#8221;. This so-called &amp;#8220;technology&amp;#8221; was broken into two parts: Gap Detection and Gap Filling. The first one is merely responsible for detecting when a Gap needs to be added to the Track, and the second one transforms a Gap into new Tickets which magically appear in-place in the Track. You must be thinking: &amp;#8220;but that&amp;#8217;s inefficient in an NSArray!&amp;#8221; Hang on, here. The first devil of all software is premature optimisation, and though I did not entirely follow my own rule as you&amp;#8217;ll find out soon, this is one of the reasons I &amp;#8220;spun&amp;#8221; the Track out of the Engine; in this way, I can completely hide how the Engine manages its Track, and if I consider it&amp;#8217;s better transforming it into a doubly-linked list, UI performance won&amp;#8217;t suffer because the Track the ViewController will be using can always represent the Track as an NSArray: 2/2. &lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s focus on Gap Detection first: what is a Gap? A Gap represents a sequence in time the Engine has no knowledge about the existence of Tickets. This means the Engine can make the mistake of adding a Gap in time where no Tickets were produced, and it can also mean a Gap can represent more Tickets than the Engine can grab in a single Pool, so filling in a Gap may spawn another Gap, the second one representing a shorter sequence of time than the first. Next, who&amp;#8217;s responsible for the Gaps? The Engine. A Gap is not a StandardTicket: it abides by the rules other Tickets do, but it is not a StandardTicket per se; it is entirely managed by the Engine, and thus shall be excluded from most tests. This means the Engine is a Supplier? Technically it is, but I don&amp;#8217;t want to burden the Engine by making it compliant with the Supplier protocol and implementing its methods. I still want the outside world (the ViewController) to know as little as possible about Gaps, so I still want the Gap Ticket&amp;#8217;s Supplier to handle the UITableViewCell and so on. The solution I opted for was composing the Standard Engine with a its own custom Gap Supplier, which keeps things elegant and at the same time allows me to keep the Engine and its Gap Supplier tight, which is exactly how they should be.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/d72f84fe671873bc1cf60b4c7d48b04b/tumblr_inline_mlml0aef3S1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;More questions: when are Gaps created? There are two situations here. The first (and simplest) one is the Gap at the end of the Track, which basically stands for all the Tickets the Engine can&amp;#8217;t account for in the history of the Universe. The second, and the most common situation, is when we form a new Pool of tickets, and the Pool and the latest Tickets in the Track don&amp;#8217;t intersect in time. This means the oldest Ticket in the Pool is still newer than the newest Ticket in the Track: therefore, there may be Tickets in between, and so a Gap is formed. How many types of Gaps are there? Two. The &amp;#8220;Infinite Gap&amp;#8221;, which is basically the Gap at the end of the Track and which will rarely disappear, and the normal Gap, which happens to cover a specific  period in time. Broken down, it doesn&amp;#8217;t seem like all of this &amp;#8220;Gap Technology&amp;#8221; is any hard, right?&lt;/p&gt;
&lt;p&gt;Pretty much all of this was written down on Wednesday, but some details were left to Thursday morning, which kickstarted my &amp;#8220;full ahead&amp;#8221; mode on this problem. I started first with the Infinite Gap, which was pretty easy: after processing a Pool, if the Track is empty, an Infinite Gap goes before the Pool, and we&amp;#8217;re done. Then came the other type of Gap, the normal one. Coming into this problem, I thought Gap Detection would be incredibly easy and that I&amp;#8217;d be able to leave how to properly detect when Tickets intersect in time with one another for the Filling part; after all, all I had to do was either add a Standard Gap or add the Pool&amp;#8217;s Tickets on top and we were done, right?&lt;/p&gt;
&lt;p&gt;I started having problems writing down the code that followed, and that should&amp;#8217;ve been a signal to me saying: &amp;#8220;This is not as easy as you thought it was. No matter how much ink you&amp;#8217;ve spilled into this problem, you still need to spill some more.&amp;#8221; Many minutes staring from my screen to my notes followed, again and again, until I finally managed to start making breakthroughs by writing code. I thought the hardest part would be making the Gap appear: I was a fool, that was the easiest part. All I had to do is simply check what I said before: is the oldest ticket in the Pool newer than the newest in the Track?&amp;#8221; If the answer is true, all I had to do is add the Gap and move along just like we used to do before. Easy peasy. What if the newest tickets in the Track were newer than the oldest in the Pool? No Gap was required, we just needed to add the new Tickets. Good luck with that, Sherlock.&lt;/p&gt;
&lt;p&gt;I attempted to write the code. It turned out very big. I never tested it, but it seemed far too big, and going against &amp;#8220;optimisation is the root of all devils…&amp;#8221;, I rewrote it again, made it shorter and prettier. I ran it: disaster. My Gap Detection was literally eating through the whole Track and destroying a lot more Tickets than it should&amp;#8217;ve. To make this whole thing work, I added a recycling functionality to our old friend the ProgrammableSupply, so the second and subsequent Pools would be filled with the last tickets of the previous one, and thus the no-Gap branch in the Gap Detection method of the Engine would be triggered. This worked, although it gave me a couple of scares, but the code I was writing was clearly not doing what I wanted it do do. My theory was pretty simple: all of the Tickets in the Track that are newer than the one at the bottom of the Pool should be discarded, because the Pool obviously carries more recent information and thus has priority over the Tickets in the same timeframe in the Track. After that, we need to find a matching Ticket in the Track, and when we do, we can stop and finally join the Pool in. No deuce. My while loop discarded a lot more Tickets than it should. Then a thought sprung to mind: a lot of Tickets were being created down to the very same second and even micro-second, which certainly that doesn&amp;#8217;t happen so often in real life. I added another functionality to the ProgrammableSupply, a delay per ticket. I set it to zero in the tests I had for the features we have already finished, but by default every Ticket took a second to create. Since the Engine is using GCD and spawning a thread per Supplier, there are still many Tickets being created in the same second (3 at a time, because I&amp;#8217;m using three ProgrammableSupplies), which is not exactly what I wanted, but it&amp;#8217;s close enough to a real-life situation, which I&amp;#8217;m keen on following with all tests. No luck: the while loop was still eating a lot more than it should. I shifted from the compare: function to timeIntervalSinceDate:, but things weren&amp;#8217;t improving. I finally set up a breakpoint plus NSLogs and found out it was discarding Tickets in the same second as the last one in the Pool, which was clearly not my intention. I modified the code so only Tickets newer (in seconds) were discarded. Still no match: If the ProgrammableSupplies recycled a total of 27 tickets, the Engine could easily eat up 40 or more. Why? I then improved the code that came after that first while loop, the one looking for a &amp;#8220;match&amp;#8221; to put both the Pool and the Track in sync. No luck. The Engine performed less aggressively, but this had a downside: there were repeated Tickets. Not what I had in mind. Heads down, I called it a day on Thursday Night.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/6e3a53df876da7531b456ebc03823aa7/tumblr_inline_mlml7eYock1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Friday morning. Of course the Engine was being overly aggressive!! The ProgrammableSupplies are each recycling a different number of Tickets, that means they&amp;#8217;re out of sync with what the Engine has in its Track, and thus we&amp;#8217;re eating more Tickets than we&amp;#8217;re recycling. It seemed like that was the key, and I was happy to get to work on that idea minutes after waking up, but I decided to go another route: tests first. I wrote the Infinite Gap Test, the Standard Gap Test, and then I went for the Gapless Pool Test (aka &amp;#8220;the problem currently at hand&amp;#8221;). I made a different Unit Test for the Gap Technology, since these tests did not run the Engine so many times and because they were much slower, using the Ticket Delay feature in the ProgrammableSupplies. First two tests were clear. I made the third one forcing all Suppliers to recycle the exact same amount of Tickets. I ran the Test once: we were overly aggressive once again. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I couldn&amp;#8217;t believe what the Console Output was saying. I ran the app in the Simulator and saw it for myself: one Supplier&amp;#8217;s Tickets were always being killed, like ten of them. Something was still very wrong. I ran the Test again, got up from my chair, walked around the house… &amp;#8220;Tests Failed&amp;#8221; said Xcode. The Engine was now not being aggressive enough, and my Test was detecting that there were repeated Tickets left in the Track. Another walk around the house… and an idea erupted: &amp;#8220;You&amp;#8217;re an idiot!&amp;#8221;. I&amp;#8217;d been failing to look at the process in two dimensions: just as the intersection of the Pool and the Track begins at the Pool&amp;#8217;s last Ticket, it also ends there. Meaning if while clearing out the Track we find a Ticket that&amp;#8217;s older than the last one in the Pool, we&amp;#8217;re in sync, because this is information the Pool simply doesn&amp;#8217;t have. A very big mistake on my part: the problem was not one-dimensional, but two-dimensional. Throughout all of this time I knew that testing with real Suppliers would&amp;#8217;ve not made this design failure so prominent, which irritated me, but once I realised it was a true error on my part to properly assess the problem, I breathed while correcting the &amp;#8220;matching&amp;#8221; loop thinking it was a mistake I would not make again, and that this was exactly the reason why I started working on a project like this to begin with. I updated the code, I ran it: &amp;#8220;Tests Succeeded&amp;#8221; it said. I ran it again, not believing my eyes: it failed. I ran it in the Simulator: it worked, no visible gaps (sorry for the pun) in the Ticket IDs. I ran the tests: success again. But something was not fully working, so this being a test, I switched the numbers, and added a second subtest to the GaplessPool: the Aggression Test. In the first subtest the Engine must clear exactly the number of tickets recycled by all the Suppliers, because they all recycle the same number, and the Aggression Test makes sure the Engine behaves aggressively when the Suppliers recycle less, meaning some information was lost, and so the Engine must clear more out of the Track because the Pool&amp;#8217;s information prevails. Tests started to fail again because the Engine was missing out a single Ticket. I looked at the debugger, and I reached a painful conclusion: the Tickets were not sorted equally in the Pool and in the Track. This caused the &amp;#8220;sync&amp;#8221; to happen when a duplicate Ticket was left out in the Track, thus failing the Test for two reasons: one, a recycled Ticket failed to be cleared, and two, a that Ticket obviously ended up being duplicated. To add insult to injury, the Aggression Test was not matching the number of cleared Tickets I expected, which it should&amp;#8217;ve, because the problem was already localised and it shouldn&amp;#8217;t be affecting this test. I looked into StackOverflow, and changed my sorting function. Instead of using a block and compare: I used an NSSortDescriptor. Tests Succeeded. I tried again. Tests Succeeded. I tried again. Tests Succeeded. Again. Tests Succeeded.&lt;/p&gt;
&lt;p&gt;Sorting with Blocks was giving me wrong results? A bug in Apple&amp;#8217;s code? That seemed strange enough, until the Tests Failed again for the same reason as before.&lt;/p&gt;
&lt;p&gt;What was exactly the problem here? Too many Tickets were being created at exactly the same time, perhaps even down to the microsecond in my Mac (can&amp;#8217;t perform Unit Tests on hardware, Xcode doesn&amp;#8217;t allow it). Would this happen with real Suppliers? Most likely no. The tests were failing because a single Ticket was out of order, and simple hacks could make this nightmare end. I could make the last Ticket in the Pool I check against move to a newer Ticket when a match fails after being in sync to prevent the sorting error, or I could check after the Pool and the Track are in sync that the remaining Tickets in the Track that are in the same second as the last Ticket in the Pool are not in the Pool (sorry for the mix of words, but it really is like this). I didn&amp;#8217;t like either. The first one was a mess, and the second one turned my whole algorithm from O(n) to O(n^2). Something faster than O(n) is clearly impossible, and going to O(n^2) would waste my (possible) users&amp;#8217; battery life because my Zealot Engine is flawed. I didn&amp;#8217;t like the feeling of building my Engine on top of a flawed design. Did the guys at HootSuite have a really hard time with this, too? How does Twitter handle all of this? Clearly, the have thousands, if not hundreds of thousands, if not millions of tweets being created and dispatched in the very same second. Who do they handle this? Ah, because every Tweet has an unique ID. How about sorting based on a custom ID?&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/3039e5d600627741cd528db8e1001255/tumblr_inline_mlmljldakw1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s see. We want everything ordered by time first, so this means our custom ID will start with each Ticket&amp;#8217;s timestamp, and since this is best represented as the number of seconds since 1970 (aka &amp;#8220;Standard UNIX time&amp;#8221;), we&amp;#8217;ll give that 32 bits of space. Then, we want to order everything by source, which for us is our enum. We need some headroom here, so we&amp;#8217;ll give ourselves 8 bits, which gives us 256 possible values and brings us to a total of 40 bits of size for our Custom ID. In case two Tickets were produced at exactly the same time by the exact same Supplier (knowing Twitter it&amp;#8217;s not that difficult), we need to break things up by user now. Considering Facebook has broken the 1 billion users, we need enough bits for that. 32 bits equals to roughly 4 billion possible values, and now we&amp;#8217;re up to a whooping 72 bits. If by any chance a user pushes two different Tweets in the same second using two different clients, we need a Ticket ID to break the tie, which puts us in 128-bit territory for our Custom ID value. 128 bits, or roughly 125 KiloBytes of memory lost per thousand Tickets only in our Custom ID. It doesn&amp;#8217;t seem like much, but I don&amp;#8217;t want to push 128-bit numbers  comparisons into 32-bit register ARM CPUs, so I&amp;#8217;m taking that off the table. What if instead of a number we represent our Custom ID as a String? I&amp;#8217;d take up a lot more memory.&lt;/p&gt;
&lt;p&gt;Admitting defeat, I called it quits on Friday night, thinking the only solution I had was the O(n^2) hack, which compromised efficiency and speed, but seemed like the cleanest solution taking into account that in most real-life scenarios the Engine could process the Pool in the ideal O(n) time.&lt;/p&gt;
&lt;p&gt;Saturday morning. I&amp;#8217;d dedicated two full days to the Gap Technology problem, three if we count Wednesday, and hadn&amp;#8217;t managed to even finish what seemed like the easiest part. I said I&amp;#8217;d use Saturday to cover for the time I lost on Monday writing Week 2, but after two days working on this until 1am, waking up early again, and dedicating all of my energy and thought to the problem, possibly doubling (if not more) the amount of time dedicated to this effort than in previous weeks, I clearly needed to lean back from the table and look at everything from afar again. Surely my mistake was again in the design. Until it came to me: the only thing I had to do, was break up the ties when the compare: function wasn&amp;#8217;t enough. If two Tickets had the exact same time, I&amp;#8217;d order them based on their Supplier. If two Tickets were produced at the exact same time by the same Supplier, I&amp;#8217;d order them by User, and if the tie was still not broken, I&amp;#8217;d use the Ticket ID, unique to every Ticket and given by each Ticket&amp;#8217;s Supplier. &lt;/p&gt;
&lt;p&gt;I knew this was the solution, I just knew it, from the moment it splashed into my mind. If you have been half of the time screaming at me: &amp;#8220;don&amp;#8217;t stop sorting using the block, just break the tie just like you said based on the idea of your Ticket ID!!!&amp;#8221;, I agree with you, this is a very big mistake on my part. But this is exactly the reason why I don&amp;#8217;t like being &amp;#8220;eaten up&amp;#8221; by a problem, because you lose focus, and you stop thinking clearly. On the other hand, it reminds you of why you do what you do.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/fb0545e246ba804853d7891de9d121e1/tumblr_inline_mlmlx0Pan31qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;In any case, I solved this very quickly during Q1 of the Bahraini Formula One Grand Prix. The Aggression Test was actually OK, I was just using the wrong #define values to make the calculations and was misplacing the brackets. I also relaxed the Aggression Test because it doesn&amp;#8217;t always have to eat through all of the missing Tickets, just clear at least the same number as was recycled and not introduce duplicates into the Track. After solving that, I added a small feature I&amp;#8217;d been needing to perform more accurate tests: an Engine restart. It does exactly what you&amp;#8217;d presume: it returns the Engine and its Suppliers to the exact same state they&amp;#8217;re in right after being alloc-inited. This is actually one small feature in my list for the Zealot Engine, which goes hand in hand with the cold-restart, aimed to being the closest thing to &amp;#8220;restoring the app&amp;#8217;s state&amp;#8221; without deleting it and re-installing it. And of course, last but not least, I also made the switch to the Track and changed all the code accordingly. The other thing I worked on was starting to commit the code to a local Git repository just before starting my work on Gap Detection.&lt;/p&gt;
&lt;p&gt;And with that, we&amp;#8217;re up for a close. I hope the ride has not only been entertaining but also insightful into what goes on making an App, and remember, this is not even an App yet! If it ever becomes one, it&amp;#8217;ll be a prettily documented one. About Week 4, I could state that my goals are Gap Filling and State-Saving. Gap Filling is in fact already done, if you think about it, since Gap Detection already inserts code into the Track, and I think I can refactor that code from the Engine and use it for Filling again, which should make the latter half of Gap Technology pretty easy to wrap up (we&amp;#8217;ll see). State-saving is basically saving the Engine state when the app closes so the next time you open it the Track is not entirely blank, and if Gap Detection was implemented well, a new Pool should automatically spawn a new Gap. Sadly, next week I need to focus on Android for a bit, but I&amp;#8217;ll consider either giving at least a day for this project, or posting about whatever work I do on Android. Thanks for reading, and I&amp;#8217;ll see you soon!&lt;/p&gt;</description><link>http://dinesharjani.com/post/48561548010</link><guid>http://dinesharjani.com/post/48561548010</guid><pubDate>Sun, 21 Apr 2013 18:18:09 -0400</pubDate><category>personal</category><category>developers</category><category>development</category><category>programming</category><category>ios</category><category>software</category></item><item><title>Week 2 - Laying down the keel</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/de6e48fe8426dc40df4ed7e62416e150/tumblr_inline_mlamstlARp1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Let&amp;#8217;s get right to it.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Week 2 was the week where I decided the occupation that&amp;#8217;d keep me working on iOS for an unforeseeable number of weeks, or at least that&amp;#8217;s the idea I was pursuing. I had a rough idea at the start of what I wanted to do, but again, I did not want to mark an &amp;#8220;X&amp;#8221; in the calendar saying &amp;#8220;this has do be done by then&amp;#8221;. No. It hasn&amp;#8217;t proven to be a good solution for me in the past, and I won&amp;#8217;t be able to change the outcome of things if I don&amp;#8217;t change the process itself. Yes, there were goals for week 2, but there were very reasonable goals, and there were goals I knew I could do without rushing in. So let&amp;#8217;s dive right in.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;First of all let me introduce you to the concept I want to build. You might&amp;#8217;ve heard about a company called &lt;a href="http://hootsuite.com/"&gt;HootSuite&lt;/a&gt;: they appeared in my radar back in 2009 when I was introducing myself to the world of technology through Engadget. They made, just like so many others, a Twitter client for multiple platforms. The difference though, was that they pursued the people riding the &amp;#8220;Social Media&amp;#8221; wave and built a software which would allow you to cross-post to multiple platforms, most notably Facebook and Twitter, the two kings in the matter.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/dba05a8bbd56a9aa87841003ec257bb1/tumblr_inline_mlan8gkzIb1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;What HootSuite will basically do for you is show you multiple streams of information no matter the source: it can be a Twitter account&amp;#8217;s mentions, a stream of specific Twitter accounts (list?), a Facebook feed, etc. and of course, since this is no longer 2009, it works with a lot more social platforms since then: LinkedIn, Google+ pages, Foursquare, Wordpress&amp;#8230; and has been refined to offer more than just &amp;#8220;information streams&amp;#8221;: you get statistics, options to monetize, and a lot of other stuff I&amp;#8217;m not that interested about right now.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What I&amp;#8217;ve always admired HootSuite for, ever since 2009, is the codebase that must be capable of handling all that kind of information no matter the source. Keep in mind whatever code is at the core of the HootSuite experience cannot know about what platforms will come next, and a reasonable software engineer/architect will tell you you have to engineer it in a way that keeps the parts that change separate from the ones that don&amp;#8217;t. You must also follow the DRY principle, which means Don&amp;#8217;t Repeat Yourself, which in practical terms means you should never have two different pieces of code (functions/classes/namespaces depending on the size and scope of your project) that do the same thing: centralize them, make everything use the same thing. In this way you force your code to do more work, and you catch bugs a lot faster, since you exercise it a lot more. And if you need to make a change, it&amp;#8217;s instantly updated everywhere else: no need to chase more code.&lt;/p&gt;
&lt;p&gt;It is not a simple problem to tackle. About why am I tackling this problem, the reason is very simple: all I want to do is practically exercise my software architecting abilities, which are important no matter who interviews you or what position you&amp;#8217;re going to work in. Going from solving &amp;#8220;programming problems&amp;#8221; to trying to do something simple in real life seems like a pretty good idea to me, and what better way to do it than tackle a problem I&amp;#8217;ve had in my head for a number of years, without actually trying to solve?&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/2c4f482491849e96df5cb4659c12ba93/tumblr_inline_mlao27iBQP1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;About a year ago, I started trying to type this idea down as some kind of Twitter client for Windows, based on WPF. I felt energized for Windows development given the fact it&amp;#8217;s the platform most of my friends use on a daily basis, no matter what phone they have. This meant once I had something worth showing I&amp;#8217;d receive a lot of support to keep it going. And I was also starting to fall in love with Metro, especially after the release of &lt;a href="https://github.com/blog/1127-github-for-windows"&gt;Github for Windows&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/4375d84a8f85b7425971a337b251dd61/tumblr_inline_mlapvnJQ6u1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;As you can see, I kind of have a knack for starting many things and not finishing them. (As well as proof of my thing for password-protection!) The main idea I had in my mind was to build a basic Twitter client, which should be much easier to do than the platform-independent near-real-time core that lies at the heart of HootSuite, and evolve things from there with the gained experience, and surprise everyone by making it a multi-platform solution. I wanted to make something similar that is &lt;/span&gt;&lt;a href="http://tapbots.com/software/tweetbot/mac/"&gt;Tweetbot for the Mac&lt;/a&gt;&lt;span&gt;, and perhaps ride on top of the Windows 8 wave and make a good client capable of staying in that split-screen mode. Yes there was &lt;/span&gt;&lt;a href="http://www.metrotwit.com/#metrotwitwindows8"&gt;MetroTwit at the time&lt;/a&gt;&lt;span&gt;, but it seemed like their standard Windows client was far ahead than their 8 release, and I could capitalize on that. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;A lot of things to keep inside your head, aren&amp;#8217;t they?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I never got the so-called Twitter client to show my basic Twitter stream: none of the C# APIs and libraries seemed to work in a straightforward manner for me, and I just simply wasn&amp;#8217;t in a mood to work through it: seemed too complicated in my head, and I needed to relax for a bit. Then photography interrupted, things changed in the Summer, and it got left there.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Back to where we are, now. We&amp;#8217;re going to do things a lot, lot, lot more different. I&amp;#8217;m not going to focus on making any &amp;#8220;app&amp;#8221; right now: at best this is just &amp;#8220;pre-production&amp;#8221;, not full production like I&amp;#8217;ve tried to attempt in the past. All I want to get done now, is basically an engine or core similar to what HootSuite must be using.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I want to write a piece of code, an architecture, a set of classes and methods, capable of handling the kind of information the engine behind a traditional desktop or mobile client at HootSuite does. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/3bcb4e24ac0c307b58f908c67251c94a/tumblr_inline_mlaotyB42q1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(This is a great book to have, by the way)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Question number one: timeframe to deliver a basic sketch of a working architecture? I set myself to do this in two weeks. Meaning week 2 and week 3 would be fully devoted to having a basic drawing in code of how such an engine could be done. I did not pressure myself to write it down and have it working, I only wanted to &amp;#8220;solve&amp;#8221; the problem on paper. This is all about software architecture, after all.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So what did I do? I started writing. Got an old but gold (it&amp;#8217;s actually made out of silver) fountain pen my Grandma gave me nearly five years ago, and set out to start writing the basic components behind all of this. To begin with, we have what I decided to call a &lt;em&gt;&lt;strong&gt;Ticket&lt;/strong&gt;&lt;/em&gt;. A Ticket is basically a unit of information: it could be a Tweet, a new Tumblr blog, a link to a new album on Facebook, a new post in an RSS Feed: any one of those. I defined an Interface (protocol in terms of Objective-C) so I could later subclass the Ticket protocol and have different kinds of Tickets depending on the information they held. There are two basic kinds of Ticket to differentiate: there are those which are plain text, like a status update or a simple tweet, and those who come with some kind of media: this could be a web link, an image, a photo album, etc. But that&amp;#8217;s the basic differentiator between Tickets. They&amp;#8217;re either pretty simple, mildy complicated, or pretty complicated. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Moving on, we have the &lt;em&gt;&lt;strong&gt;User&lt;/strong&gt;&lt;/em&gt;. The User is what you think it is: it&amp;#8217;s the unit of information covering who is responsible for producing a certain Ticket. This means a Ticket has a weak link pointing to the User who created it, or at least a means to uniquely identify it. Again, the User is defined against a protocol, so we can have different kinds of Users if we need them, or if we need to hold extra information in any of them. By default, they carry the minimum amount of information: Full (real) name, username or screen name, gender if available, birthday, a link to its avatar, etc.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Next up: the &lt;em&gt;&lt;strong&gt;Suppliers&lt;/strong&gt;&lt;/em&gt;. This is where things start to get really interesting. I actually designed this the other way round, from top to bottom, but decided explaining it the way I started to implement it (bottom to top) was the right way. A Supplier is a source of information: it handles its own Tickets and Users, which means a Ticket should have some kind of information about what kind of supplier it belongs to, and every User should know to which Supplier it belongs to, again, through a weak link against it. A Supplier produces both Users and Tickets, and thus, it is the first component of our architecture that really knows which specific classes (protocol implementations) it talks to. This is important. A Supplier strongly links to its users, and forms its own &amp;#8220;family&amp;#8221; of products. In its own way, a Supplier is a content factory. I would not really describe it as a Factory pattern, because my idea was that the Supplier should be the most flexible component in the whole system. It&amp;#8217;s the one that adapts depending on what kind of information it needs to bring: RSS, Tumblrs, Tweets, etc. And whom does it feed the information to? That&amp;#8217;d be the &lt;em&gt;&lt;strong&gt;Engine&lt;/strong&gt;&lt;/em&gt;, of course.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The Engine. I&amp;#8217;m going to define the Engine as the Data Controller. It is the closest piece of our system to the UI, and it acts as the component in charge of making sense of all the Suppliers&amp;#8217; information as well as the requests the user makes through the UI. If you&amp;#8217;re familiar with Android, the Engine is the true Adapter, or provider of information. In iOS, this means the TableViewController talks to the Engine and receives its content through the Engine. Thus, the Engine manages the suppliers, notfies them when the user is requesting for new information, receives all the latest information from its Suppliers, makes sense of it, and gives it back to the TableViewController. Simple enough?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;All of these concepts were pinned down by Monday evening. Having done so, I started coding it down. I decided not to worry about blocking the main thread here, leaving any kind of asynchronous work in the back of my mind for now. What I really wanted to do, was to write the basic architecture I&amp;#8217;d just designed, and see it working. It did.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/8179078310e9fbc33cebc8f17424085c/tumblr_inline_mlapuzNnY31qz4rgp.png"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It was a very pleasant to see it working. On Tuesday I finished writing all of the code, corrected some protocol properties here and there, and got it up and running. I implemented the standard &amp;#8220;Pull-to-refresh&amp;#8221; API provided by the TableView (by the way, Xcode still doesn&amp;#8217;t allow you to &amp;#8220;link&amp;#8221; to the Outlet in IB; you must set the selector in code), and after every refresh two new tickets were added. I wrote some Dummy implementations of the Supplier and User classes as well as the Ticket. The Engine was by far the most developed component, since it had to query all of its suppliers for real. One was enough for me, so I simply detect whether all suppliers have provided their &amp;#8220;goods&amp;#8221; by tracking how many have called the Engine callback block in an NSInteger __block variable. Not the best solution, I have a much better one in mind, but again, this was just a simple proof of concept: I wanted to see it working. As for the name, I called this concept &amp;#8220;the Zealot Engine&amp;#8221;. No class actually bears that name, although protocols start with the &amp;#8220;ZE&amp;#8221; moniker. As to why &amp;#8220;Zealot&amp;#8221;, you must&amp;#8217;ve noticed most of the names don&amp;#8217;t really carry a real resemblance. Tickets? Supplier? Engine? The names used in the code, the concepts guiding the development only need to mean something to me, so I pursued this line. The current Engine implementation itself is called &amp;#8220;Standard Engine&amp;#8221;, in honor of the &amp;#8220;Standard Model&amp;#8221; used in Physics and the fact the Higgs Boson or &amp;#8220;God Particle&amp;#8221; finally &lt;a href="http://www.wired.com/wiredscience/2013/03/boring-higgs-results/"&gt;made its appearance last year without disrupting it in any way&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/bc53c70c37156e416ba9c4691251a37d/tumblr_inline_mlaqpkSHGw1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Before we move on, just a couple more details in the implementation side of things. The cells you see in the image look like standard &amp;#8220;Subtitle&amp;#8221; cells to you, and they are. The interesting part here is that I made every Ticket have a weak link to its Supplier, too. Why? Because I added these two interesting methods to the Supply protocol:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/4d0aad0a9e1d2f1692e4e6458b9eddf7/tumblr_inline_mlaxowS3Pd1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Yup. Neither the Engine nor the TableViewController displaying this kind of information is responsible for handling a Ticket&amp;#8217;s onscreen representation. Who&amp;#8217;s the one that really knows exactly what kind of information a Ticket carries? The one who created it, its Supplier. So what the TableViewController really has to do is grab every Ticket&amp;#8217;s Supplier and ask it to provide him with the final UITableViewCell. Simple and elegant. The second method is for the future, when we decide to &amp;#8220;expand&amp;#8221; the available information and require a new UIViewController to come on screen. Who&amp;#8217;s the one who&amp;#8217;s going to know who is exactly the best class to display a certain Ticket&amp;#8217;s characteristics? You got it. The Supplier.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Also, about how the Engine stores all of the Tickets, the simplest solution was an NSMutableArray. This array has a &lt;em&gt;readonly&lt;/em&gt; property returning an NSArray, so no one can externally modify the contents of the Engine. But displaying its contents presents a problem, which is that the array itself grows adding new stuff at the end, and I want to display content from newest to oldest. To keep the array ordered in this manner, we&amp;#8217;d have to constantly be reordering it to keep it in sync with what&amp;#8217;s on the screen. To go around this, I inverted the way the Tickets are displayed: instead of displaying array[i] to array[[array count] - 1], what I do is display array[[array count] - i] to the end; this makes perfect sense, because adding new data to the array is best done at the end (conceptually at least), so every time we update we only add the new Tickets in oldest to newest order at the end of the array inside the Engine, and everything works.&lt;/p&gt;
&lt;p&gt;With what I call &amp;#8220;the basic mechanism&amp;#8221; working done, on Wednesday I set out to improve it by adding asynchronous operation. I wanted to add sleep commands inside the supplier and see how the tableView refreshed without blocking the UI. I read a lot on the subject and watched multiple Apple sessions. In the end, I got it working with a concurrent queue GCD I create myself, and I add the barrier inside the Engine (code) block that every Supplier calls back so the critical section is mantained: this is because we don&amp;#8217;t want multiple threads &amp;#8220;touching&amp;#8221; the code that adds new tickets to the Engine nor the counter keeping track of how many Suppliers have delivered. I also gave a name to all the fresh tickets being delivered by the Suppliers before they&amp;#8217;re put in final order by the Engine and added to the internal array of tickets: a &lt;em&gt;&lt;strong&gt;Pool&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/b079e01b66b9072cb3074226268062d5/tumblr_inline_mlazkqR3TM1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;No, I&amp;#8217;m not talking about &lt;/span&gt;&lt;em&gt;that&lt;/em&gt;&lt;span&gt; kind of Pool. Nor was the pun intended. I could&amp;#8217;ve actually called it &amp;#8220;Basket&amp;#8221; for example, but I thought the name Pool was very common in Computer Science literature (Thread Pools, anyone? Just like the one we&amp;#8217;re implementing behind-the-scenes) so I went ahead with that name. So, the basic idea is: the Engine gets called to refresh and add new Tickets from the TableViewController running in the main thread: the Engine will then call every supplier to deliver new tickets asynchronously in a new concurrent thread (I decided to use Grand Central Dispatch instead NSOperations). Every time a Supplier wants to deliver new tickets, it calls the block of code the Engine gave them: this block has an asynchronous barrier making sure only one supplier is executing that code at the same time. This code checks out the supplier and adds the new tickets to the Pool being made. If all suppliers have delivered, the Pool gets processed (all Tickets are re-ordered from oldest to newest and added at the end of the Engine&amp;#8217;s main array of Tickets) and the TableViewController gets notified. After a refresh, the new Tickets appear onscreen. Not trying to be heavy on you, just giving you a way to confirm any doubts I might&amp;#8217;ve lead you before :)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This was finalized by Thursday. But I only had a very basic setup: every time you called for refreshing, only one Supplier was called adding two new tickets. Yes, making the Supplier take multiple seconds to deliver those tickets worked as expected: the UI was still active and the GCD code was working as expected. But I needed to really test this. I wanted a way to test the engine to the max, put it under stress, and make sure all the different parts of the code I&amp;#8217;d made thus far were really working: the asynchronous code, having multiple suppliers, the barrier controlling access to the critical section of code, and of course making sure those threads weren&amp;#8217;t making the Engine lose any tickets. Plus, the Tickets always need to be in the right order, from oldest to newest, from the beginning to the end of the Engine&amp;#8217;s internal array. The answer to this was Unit Tests.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/2671b37746689940520b2f80c39caf21/tumblr_inline_mlazp5miAs1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;By Friday I had them working, and after correcting some math operations, it all turned all right. I made a new Supply, which I called the ProgrammableSupply, because I can change its name at runtime, the number of users it has, and the number of Tickets it produces in every new Pool. The addition of this ProgrammableSupply made me realize one thing: I don&amp;#8217;t want any of the code in the Standard Engine to change, and yet, changing the Suppliers meant entering the Engine and changing some code. So what did I do?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;At first, I thought of it as a real Factory Pattern: the Engine would be composed of a new class (or family thereof) that&amp;#8217;d be responsible for creating and initialising all of the Suppliers in use by the Engine. The Engine itself does not need to know who its suppliers are, only their interface, which is common and provided through the Protocol we&amp;#8217;ve spoken about before. Then I decided it&amp;#8217;d be a new component, the &lt;em&gt;&lt;strong&gt;Commander&lt;/strong&gt;&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;The Commander is responsible for creating and mantaining all of the Engine&amp;#8217;s suppliers, and thus, if everything goes all right, I can build every single feature I want into the Standard Engine and keep the Suppliers completely detached from it. The Commander and the Suppliers will be the ones holding specific implementations, but that&amp;#8217;s their job.&lt;/p&gt;
&lt;p&gt;With everything tied, I dropped work on Friday at about 9pm. I&amp;#8217;ve not worked as much as you&amp;#8217;d imagine on this: it&amp;#8217;s been a balance between giving it around 2-3 hours at the desk plus many minutes or even hours while doing other mundane tasks thinking about where to go next and what could be changed. But this is the reason why I wanted to move slowly: I want to get it right, and not find out later that I&amp;#8217;ve been taking care of 95% of the cake but left a 5% with pretty sharp edges to deal with.&lt;/p&gt;
&lt;p&gt;Surprisingly, instead of taking around two weeks I took just two days to have a fully working prototype, which leaves me at odds with what I&amp;#8217;m going to be able to accomplish this week. Will it be a lot? Will it only be a little?&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s been a very long post, so I&amp;#8217;ll leave you to fully revise everything I&amp;#8217;ve written for the past two days. If you allow me, in the mantime I&amp;#8217;ll keep going. See you next week :)&lt;/p&gt;</description><link>http://dinesharjani.com/post/48047527729</link><guid>http://dinesharjani.com/post/48047527729</guid><pubDate>Mon, 15 Apr 2013 12:31:00 -0400</pubDate><category>personal</category><category>developers</category><category>ios</category><category>software</category><category>Architecture</category><category>development</category><category>programming</category></item><item><title>Week 1 - Password Protection</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/e7b802c46ea8f3702f72afe03d9457b3/tumblr_inline_ml8ryk80ci1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;OK, time to fill you in on what&amp;#8217;s been going on.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;21 days after my last post, it&amp;#8217;s time to bring you back up to speed. I have been publishing some photography, as you&amp;#8217;ve seen from my Twitter and Google+ pages, and even though I&amp;#8217;d normally be posting my own words next to all of them, I haven&amp;#8217;t: something else has been eating into my writing, which is programming.&lt;/p&gt;
&lt;p&gt;Up until two weeks ago, I&amp;#8217;d been heavily working on picking up my iOS skills which had been pretty much left to dust since the Summer of 2011. Back then I was pursuing a very, very big project which was completely out of scope for the time I had available it even if I was unemployed back then (the primary reason why I took the chance to follow it). Now, I know things don&amp;#8217;t count unless you finish them, so that scar has been on me since back then: a ghost telling me there&amp;#8217;s something I set out to do, but failed to deliver.&lt;/p&gt;
&lt;p&gt;The specific reasons why that project failed are not for today to discuss. What you should know though, is that it&amp;#8217;s been a weight I&amp;#8217;ve been carrying over me for a very long, long time, and perhaps I might sought out to lift it off my back now, step by step, correcting everything I did wrong that time, and not &amp;#8220;running into&amp;#8221; things, but eating the cake piece by piece: starting from the outside, and carefully running to the inside from all sides, not biting from different angles to eat it from different directions managing different goals at the same time. I&amp;#8217;m going to take this slow, but in a very methodical manner. &lt;br/&gt;&lt;br/&gt;&lt;!-- more --&gt; Two weeks ago, just as I published my words on &lt;a href="http://dinesharjani.com/post/46156599758/lara-crofts-tomb-raider-2013-is-born"&gt;the last Tomb Raider game&lt;/a&gt;, I&amp;#8217;d also managed successfully to complete Ray Wenderlich&amp;#8217;s excellent guide to iOS: I bought both the &lt;a href="http://www.raywenderlich.com/store/ios-apprentice"&gt;Apprentice Bundle&lt;/a&gt; and the &lt;a href="http://www.raywenderlich.com/store/ios-5-and-ios-6-by-tutorials-bundle"&gt;iOS5 &amp;amp; 6 by tutorials&lt;/a&gt;. It&amp;#8217;s not &amp;#8220;excellent&amp;#8221; because it succesfully targets people who haven&amp;#8217;t programmed in their life (it ramps up far too quickly due to how iOS and Objective-C are and the example apps the book tries to make) but because it explains what it does, and it goes sufficiently in-depth. This is what I like about books like &lt;a href="http://commonsware.com/"&gt;Mark Murphy&amp;#8217;s on Android&lt;/a&gt;: they explain why they&amp;#8217;re doing what they&amp;#8217;re doing in their code. It&amp;#8217;s not just &amp;#8220;this is the code for doing X&amp;#8221;. No. It&amp;#8217;s more like &amp;#8220;the API wants this, so we&amp;#8217;re going to give it what it wants in manner Y&amp;#8221;. This is essential to learning a new platform, since just copy/pasting code from StackOverflow and fighting the System&amp;#8217;s APIs is not the way to move forward: you&amp;#8217;ll constantly hit walls and wonder why other people don&amp;#8217;t. It is something I miss from Assembly and the likes of pure C/C++ terminal code not based on frameworks you don&amp;#8217;t know, but that&amp;#8217;s just the state of modern development these days.&lt;br/&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Moving on, after that I decided it was time to do something after having just finished the Apprentice Bundle, or else my recovered iOS skills would slowly fade away once again. That&amp;#8217;s when I remembered one of the things I like the most when writing a new project: protecting it.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/907a54c094bf08e8f04c4a0cd1d43843/tumblr_inline_ml8v4m27nR1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;em&gt;(Early image of the project I was working on in Summer 2011)&lt;/em&gt;&lt;br/&gt;&lt;br/&gt;Even back in the Summer of 2011 when I had a project in front of me, the first thing I wanted to do was write some code around a basic SplitViewController to ensure any time the app would run it&amp;#8217;d be password-protected from anyone (friends, family) who&amp;#8217;d catch eye of &amp;#8220;that strange icon&amp;#8221;. And if I did it right at the beginning, password protection would be a feature I did not have to worry anymore. This made my 2011 Project turn around and put this feature first and foremost: requiring me to successfully implement password protection by tapping a button, by turning on the iPad after using the app, by using the app for the first time, and of course, being capable of both setting and unsetting the password. Last but not least, I also had to save all of this securely and behind the app&amp;#8217;s preferences. If I were going to do something, I&amp;#8217;d better do it right from the start.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What looked like a &amp;#8220;basic feature&amp;#8221;, as you can see, simply wasn&amp;#8217;t. A lot of code had to be written to go around and build that feature, starting from the Preferences and the handling of the password&amp;#8217;s encryption. Now, I&amp;#8217;ve always liked Computer Security: I love the idea of hiding secrets and being able to efficiently protect them, but I&amp;#8217;ve got to admit there&amp;#8217;s not a lot I know about real Cryptography. I have the basic ideas planted in me, but I don&amp;#8217;t know a whole lot. What I can tell you is, there are a couple of rules that don&amp;#8217;t hurt when it comes to securing any kind of system: &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;span&gt;1) NEVER keep passwords in plaintext&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;2) The LESS information about the user and his/her password you have, the better&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;3) [Computer] Security is only as good as the WEAKEST LINK in its chain&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;span&gt;I&amp;#8217;ll review them very briefly: you&amp;#8217;re going to say &amp;#8220;of course I&amp;#8217;m never going to store the password in plaintext, that&amp;#8217;s why we use fancy algorithms to encrypt it!&amp;#8221;, but have you thought about how you&amp;#8217;re going to check whether the password is correct or not? Surely you&amp;#8217;ll decrypt it, compare it with what the user just introduced, and then verify if it was correct or not. DON&amp;#8217;T. Simply encrypt whatever the user types, and compare that to the encrypted password, but ever touch the password without any kind of encryption.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;About numbers two and three: if you can avoid storing the password and the user&amp;#8217;s credentials, go ahead. This goes hand in hand with the third rule, which is that no matter how good the strongest part of your security system is, hackers only have to break that poor little code with the tiniest amount of responsability to break into you. I&amp;#8217;m not personally a computer forensic nor do I have any idea of how to protect myself against each and every kind of attack our software is prone to. But the above principle remains: the least we know, and the more we can stand on the shoulders of others who know more than we do, the better. Our app will handle less confidential information, and if someone manages to break our security, we should minimize the chances of that information being of any use for them as much as we can. We are not being stupid and or &amp;#8220;bad developers&amp;#8221; for following this principle: we&amp;#8217;re simply being smart about what we&amp;#8217;re good at doing and about what we&amp;#8217;re not. We&amp;#8217;re acknowledging what our strengths aren&amp;#8217;t and protecting ourselves from them, taking measures. That&amp;#8217;s what adults do. &lt;/p&gt;
&lt;p&gt;Back to my password code. See how the simplest of things raises so many concerns? My lack of vision is probably the single most tallest wall I hit and fell at many times two years ago, I mistake I wish not to make this time. But before thinking about making something, once again, I&amp;#8217;d like to protect it: standing on the shoulder&amp;#8217;s of iOS 5 ViewController Containment APIs, I&amp;#8217;d like to make a small re-usable component I can call in from anywhere to protect a certain iPhone ViewController. And we&amp;#8217;re going to tackle this bit by bit.&lt;/p&gt;
&lt;p&gt;How will this new component work, exactly? The ViewController (henceforth VC) requiring protection will be responsible for asking for it, by alloc-initing my component, which will automatically insert itself in the parent (VC) View, present itself with some cool animations, and prevent the user from moving forwards until the password is introduced. When it is, it&amp;#8217;ll make way for the VC that called it and restore the original view, successfully being dealloc&amp;#8217;ed after removing itself from its parent&amp;#8217;s view. From a Software Architecture point of view, this means the outside world is responsible for knowing whether it wants to be protected or not (the password protection setting). That&amp;#8217;s OK, I only want to build the component for now and that&amp;#8217;s where my primary focus will be.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/be9873581df679b29383b1941a3bc481/tumblr_inline_ml99amdzta1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(The Password Protection screen for my 2011 Project)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Next. We can show the Password component, and dismiss it, all with just a couple of ViewController Containment API calls in the component itself (it&amp;#8217;s its responsibility). &lt;span&gt;How de we encrypt the password once the user introduces it? Surely iOS must have some AES encryption algorithm or API? It does, but it&amp;#8217;s not the correct solution. One simple visit to Google and a link to StackOverflow reminded me that the best way to store passwords in iOS is actually, the platform&amp;#8217;s Keychain. It&amp;#8217;s a common API for both (Mac) OS X and iOS, and the best part is, I didn&amp;#8217;t have to write the code to talk to the Keychain API, which is not an Objective-C API, but classic-C based. How did I not write the code for that? &lt;/span&gt;&lt;span&gt;Well for starters I picked it up from that 2011 project, since I remembered that was one of the very few parts that worked really well; it&lt;/span&gt;&lt;span&gt; turned out, there was a guy I respected a lot in terms of iOS development who runs the blog &lt;/span&gt;&lt;em&gt;Use Your Loaf&lt;/em&gt;, &lt;a href="http://useyourloaf.com/blog/2011/06/01/ios-and-keychain-migration-and-data-protection-part-2.html"&gt;and he wrote a nice and concise piece of code to talk to the Keychain&lt;/a&gt;&lt;span&gt;. Back then, I wrote it back myself in Xcode, copying it by hand. Why did I waste that kind of time? Because copying it by hand would give me a chance to look at it line by line and understand more or less the idea behind what that code was doing; I don&amp;#8217;t need to be an expert of every single corner of an SDK, I only need to know how and when to use the correct parts of it, but trying to understand code that&amp;#8217;ll be in something I&amp;#8217;ve done never hurts.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Two problems solved. One thing now: the VC calling us knows whether it wants to be protected or not, but after that, everything password-related is our component&amp;#8217;s responsibility  Where do we store whether a password has been set or not, to know if we must ask the user to set it? Though I could rely this to another component, touching the password is our responsibility  and so is both setting it and possibly unsetting it, or at the very least delete it, at the user&amp;#8217;s request. Setting it though, should be pain-free. With a simple block callback we can notify the component&amp;#8217;s user whether the password has been set or not so he/she can update whatever code he/she needs to. But we need a safe spot to store whether a password exists or not. We could use the Keychain for that, but I preferred to tackle the Preferences problem because a class capable of handling key/values and storing it in a safe manner is definitely handy. Especially if I can make use of it again. But how? Subclassing NSMutableDictionary? A new class composed with an NSMutableDictionary? I opted for the latter, and used the iOS File Protection API after carefully examining &lt;a href="http://www.raywenderlich.com/6475/basic-security-in-ios-5-tutorial-part-1"&gt;this Ray Wenderlich tutorial&lt;/a&gt; among others. Although the File Protection API only works if the user sets a passcode on their device (it works through hardware encryption), it&amp;#8217;s a good hassle-free solution, relatively easy, short, and can work just as an NSMutableDictionary adding the proper methods. We only have to worry about the data protection when loading the Preferences from the file and when saving it. Done.&lt;/p&gt;
&lt;p&gt;With these pieces on hand, the only remaining bits to complete the set where the animations and a little bit of refinement. I did not give the end result some nice colors and textures nor did I write an API to unset the password: I just wanted a couple of features and I wanted to set myself a very reasonable goal as a first step. It was the first time I was doing something in iOS in two years, and I wanted to start well, fresh, energized, and with a small success to lean on, and thankfully I did.&lt;/p&gt;
&lt;p&gt;UIView animations turned out to be a little pesky, since they don&amp;#8217;t necesarily work &amp;#8220;linearly&amp;#8221; and instead opt for lazyness, taking &amp;#8220;the shortest route&amp;#8221; to move Views. I also found out Auto-layout was screwing any type of animation I was working on, so I set it off in the Password component (the ViewController&amp;#8217;s own nib): I did not want to bother either about the larger 4-inch screen or landscape mode. Not today.&lt;/p&gt;
&lt;p&gt;What I did work on is in notifying my test (subject) VC of when the app got suspended and/or resumed: this is what eventually sets off the Password ViewController. A much, much better solution than inserting code in the AppDelegate, if I must say.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/c76dac51895d851541fd2e60ed6f5671/tumblr_inline_ml992bx30g1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(The real deal running in the Simulator)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;All in all, I can admit I&amp;#8217;m pretty satisfied with the results. Granted it was not much that amount of work since some of it had been done before, but the thing I liked the most was that I did make a re-usable Password Protection screen  (which can be expanded for iPads, too), that it works in a respectful manner with Apple&amp;#8217;s iOS APIs and Objective-C, and that I hit my goal by Friday afternoon just before lunch. Sweet!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Tomorrow marks the start of week 3, so as you can imagine, week 2 is where I start setting up goals leading to something more than just a re-usable iPhone ViewController. I&amp;#8217;d love to get it done tomorrow itself, but if I do that&amp;#8217;ll be less time during the week to actually do some progress: this is the main reason why I&amp;#8217;ve been posting pictures and not writing about them. I prefer to spend time working on this rather than dedicating 1-2 hours to writing. But I understand in this case it&amp;#8217;s of extreme importance to get it done, so I think I&amp;#8217;ll make an exception for tomorrow, and get you week number two. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;By the way, please feel free to comment or provide your own opinions on my work :)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span&gt;(Note: You&amp;#8217;ll notice the cover picture for this post shows a &amp;#8220;Lock&amp;#8221; button on the upper right corner. I removed it after detecting when the app resumed worked to lock the screen, and kept an older build in my phone for the shot.)&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;</description><link>http://dinesharjani.com/post/47968765030</link><guid>http://dinesharjani.com/post/47968765030</guid><pubDate>Sun, 14 Apr 2013 13:53:00 -0400</pubDate><category>personal</category><category>developers</category><category>iOS</category><category>programming</category><category>security</category><category>development</category></item><item><title>Lara Croft's Tomb Raider (2013) is born</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/d25b80d3c0d24429656773c57fb244dc/tumblr_inline_mk5uviJJRv1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I&amp;#8217;m honestly having a hard time just coming up with a title for this post. Wait, I just figured it out.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Um. Honestly, I&amp;#8217;m not really sure about where to start. My history with the Tomb Raider series began somewhere around 1999/2000 when Tomb Raider III came as part of one of those &amp;#8220;magic CDs&amp;#8221; filled with games of the Win98 era. Lara could gasp, shoot, kill and even dodge incoming boulders, but my (pirated) copy of the game had no music nor voices for Lara. I was also horrible at it. I played it again, and again, trying to solve it on my own to no avail. &lt;a href="http://youtu.be/7ySvlmQdAMo"&gt;I did the third level with the bike&lt;/a&gt;  many times, but I wasn&amp;#8217;t really good. Just felt frustrated playing a game I liked very much but that I couldn&amp;#8217;t really do much about.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/0d1e5a11b6215d84f769c15a1c179159/tumblr_inline_mk5wxkjrcQ1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I would later play Tomb Raider IV somewhere in 2001/2002/2003, finishing the intro level focused on a young Lara, and when that was over, I hit a difficulty wall again.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;During that time, I used to think sometimes about how Lara was constantly in the crosshairs for being something &amp;#8220;spoling&amp;#8221; the minds of boys who&amp;#8217;d later look for the exact same impossible body shapes in their lives. Even as a kid, it seemed like quite a joke to me. I mean, you&amp;#8217;d look at her, or it since she barely resembled a real girl, and clearly see that was an impossible body. It&amp;#8217;s a nice idea to play around with in a game, but it&amp;#8217;s no where real. So no, that wasn&amp;#8217;t in any way spoiling my head. Not mine, at least.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/09346b4115ea8d190a2c3d155060404a/tumblr_inline_mk5wpmjxEw1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;As the years went through, I heard about what happened to Core Design, how Crystal Dynamics wanted to re-energize Lara and had brought her back with Legend but didn&amp;#8217;t quite make it with Underworld. Legend was OK to put Lara back in her feet, but Underworld was not taking the franchise anywhere you&amp;#8217;d want to go. Or spend time playing Lara.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So I lost track of Lara, mainly. I just didn&amp;#8217;t like what she&amp;#8217;d become in my mind. She stood like an impossible body, composed of legs, limbs, a torso and most importantly a face and expression in which I didn&amp;#8217;t see anything I liked. The whole idea of that Lara just wasn&amp;#8217;t appealing to me anymore, and I didn&amp;#8217;t understand how I&amp;#8217;d spent so much time with her in my childhood trying to solve those puzzles in the jungle. And the city (via cheats) because I loved her night outfit.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/a51a363260d0e7aeec8273944e33deb8/tumblr_inline_mk5xtzNrZX1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I wouldn&amp;#8217;t go as far as calling it &amp;#8220;hate&amp;#8221;, but she was simply empty in my eyes. A shell from an old era I thought did not have a reason to exist. There was no Lara Croft really, just another &amp;#8220;Tomb Raider&amp;#8221; game in which you played the same character, or seemingly did, and did the same stuff as before. &lt;/p&gt;
&lt;p&gt;&lt;span&gt;Then the fresh waters hit in June 2011, and I just couldn&amp;#8217;t have enough of this new Lara. It seemed like this was the real Lara Croft, not the other one. What was the other one, now that I came to think about it? A shell composed of impossible jumps shooting ahead wherever she went to get what she wanted?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/fd3eeaddefd8908e38c7bfdb32655ecb/tumblr_inline_mk5xuvN9it1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="http://dinesharjani.com/post/24841850670/a-very-welcome-reboot"&gt;I went so crazy after news of this new Lara hit&lt;/a&gt;, I revisited her entire story reading the plot behind every game in Wikipedia, trying to get a feel of what had really been going on with the character behind that old face.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Beyond what words could say though, this was a Lara I really wanted in my life, or at least a new character I felt deserved a chance, and I wasn&amp;#8217;t wrong in any way.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/71694a92fd3d401ec708f350f630167d/tumblr_inline_mk5vuefUEM1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Back to the game. I started playing it last Saturday, &lt;a href="http://dinesharjani.com/post/45600386706/thoughts-on-starcraft2-heart-of-the-swarm"&gt;mere hours after finishing Heart of the Swarm&lt;/a&gt;. I played about 3-4 hours to fill my all-nighter into the first round of the 2013 Formula One Championship, and I&amp;#8217;ve got to say picking up the game so quickly after finishing HoTS was a mistake. I practically went through those hours because I realized the game was keeping me awake and I knew if I tried to do something else sleep would catch up with me. More than a couple of times through those hours I felt like stopping and putting it down, almost not feeling a reason why I should really continue playing it.&lt;/p&gt;
&lt;p&gt;I ended up having fun, until I hit a roadblock and decided it was time to watch the race. Then I slept, had lunch, wrote the piece on Starcraft II&amp;#8217;s first expansion, and just couldn&amp;#8217;t stop thinking about anything else than Tomb Raider. I didn&amp;#8217;t feel as connected to it as I did to Starcraft II, but &lt;a href="http://dinesharjani.com/post/41622307701/the-relentless-month-of-gaming"&gt;we were in the month of relentless gaming&lt;/a&gt; (which is now over), and I really wanted to see it through, so I played about 2-3 more hours that Sunday, after hitting another roadblock and wondering whether I&amp;#8217;d be able to continue through the adventure.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/14d0fd36b118980591f431525076ff80/tumblr_inline_mk5xvlzW281qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The next week began, and through the majority of the days I wasn&amp;#8217;t actually feeling too good for the first time in months. A small ray of light hit me on Thursday evening when I suddenly thought to myself: &amp;#8220;what if you consider you&amp;#8217;ve done enough for today and get back to Tomb Raider?&amp;#8221; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s when I really started enjoying this game.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/fc07cc7fe0f593fee1f4bca478848c7d/tumblr_inline_mk5w58ORDD1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Lara became herself. I started understanding her, I started understanding what the game was all about, I started understanding why I had to do everything the game asked me to do (saving my friends and getting out of there), and I really started to understand the mechanics, the skill points, and how trying to kill everyone by a direct 1-shot to their skulls made me reminisce of the old Counter-Strike days in a way I found deeply enjoyable.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Come to think about it, it&amp;#8217;s all a mix of many well thought things that make this new Tomb Raider what it is, most important of all the protagonist Lara Croft. I feel the game is called Tomb Raider just as a service to the original titles, not because it should really have that name. This Lara is not a Tomb Raider; this is the real Lara Croft. The Lara with a personality, with a heart, the Lara who despite being surreally gorgeous (more on that later) has aspirations far from enjoying her money and making use of any quality time she can steal from good looking boys on sight. In one of the game&amp;#8217;s diaries, Sam even suggests she had to drag Lara to meet cute guys&amp;#8230; that&amp;#8217;s a depth I&amp;#8217;m more familiar with in TV Shows, and all I can think about is that we have Rhianna Pratchett to thank for all of this.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a29b8db427b9cc6a2f2f5e461b1f5d88/tumblr_inline_mk61fvuQ8c1qz4rgp.jpg"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;I mean, this game is SO GOOD. It feels so complete, there are seemingly no holes, it&amp;#8217;s easy and challenging at the same time, you grow to care and protect the character, and the finale is truly incredible. It seems like this game has been thought about tirelessly again and again, making sure every detail was looked after to make sure the package became a truly cohesive experience. I can really find no &amp;#8220;buts&amp;#8221; overall. Camilla is fantastic as Lara; if there is a new film (I wish there wasn&amp;#8217;t), I&amp;#8217;d go as far as suggesting Camilla should dub whatever actress lands the role.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/27c3bab31a9e99d871c36229c5b10c4c/tumblr_inline_mk61iw3j7b1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Part of what makes this game so good is the feeling that the ending is really open. About halfway through the game, I really thought it&amp;#8217;d ended!! And to my great surprise, it kept going on, and on, and on. Total playtime for me had to be about 12-14 hours, and the last 3-4 happened yesterday (Saturday) morning after the 2013 Malaysian Grand Prix Qualifying session. I just couldn&amp;#8217;t get up from my seat. And in the evening I began reading into the character&amp;#8217;s story to write this piece. By the way, the retrospective I liked the most was &lt;/span&gt;&lt;a href="http://youtu.be/f067cmw7AfQ"&gt;this one&lt;/a&gt;&lt;span&gt;, although it lacks the &amp;#8220;Underworld&amp;#8221; part.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/db46feee058aae520879bbac7dfe39f5/tumblr_inline_mk5y4i3OyS1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;But now it&amp;#8217;s time to enter the only &amp;#8220;but&amp;#8221; I have against this game. Not necessarily about the game itself, but around Lara&amp;#8217;s character design.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s no denying they had to make the girl insanely beautiful, and I agree with that. To me, I like her the most from the CG renders, and her in-game looks lose against those of Starcraft II&amp;#8217;s Sarah Kerrigan. I&amp;#8217;m all face &amp;amp; eyes when it comes to girls, or &amp;#8220;features&amp;#8221; as my Grandma&amp;#8217;d put it. Maybe my i7-920, 8GB 1033 RAM and GTX260 didn&amp;#8217;t allow me to contemplate Lara&amp;#8217;s features better, but I think her face is a bit different than the one seen in merchandise, artwork and CG trailer, and to me Sarah&amp;#8217;s face looked better inside the game.&lt;/p&gt;
&lt;p&gt;With that behind, I&amp;#8217;d like to concentrate on another matter, her body constitution. This new Lara is definitely shaped to be real, I mean, she&amp;#8217;s not very tall, she looks healthily thin, her clothes aren&amp;#8217;t exactly high-fashion, her hair is tied in a very simple ponytail; these are all details looking to providing the image of a Lara who&amp;#8217;s rather a very approachable girl. You get the feeling a girl you might look someday walking down the street could look as good as her if not better. Perfect. I agree. Trying to provide a Lara closer to reality doesn&amp;#8217;t mean her body can&amp;#8217;t be gorgeously shaped.&lt;/p&gt;
&lt;p&gt;But this is were I started to figure out a big detail.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/b5eceb637261aeaeca8482152b456854/tumblr_inline_mk5yx7Q4XI1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The game is constantly trying to make you realize how generous Crystal Dynamics was with new Lara&amp;#8217;s breast size. And by that I mean shots like this, where it&amp;#8217;s seemingly clear she&amp;#8217;s actually not so real. Girls do not need a huge breast size to be stunning, just look at all those VS top-models earning hundreds of thousands of dollars an hour who aren&amp;#8217;t so gifted as Lara in that sense. I don&amp;#8217;t quite understand why she had to be given a big cup size if they wanted to make her look more real. I understand, perhaps, that it might&amp;#8217;ve happened because they simply wanted to emphasize how young and stunning Lara should be, and since her clothes don&amp;#8217;t play so much to those strengths, in situations like the one below they wanted to make sure she she still looked like a really attractive woman, and in camera situations like these in which the game so often finds itself, well, you just needed to give her a certain breast size in order to make her figure as noticeable as they wanted it to be in the dark.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/204c4b61305b45eaf4257e9fd29b1c7d/tumblr_inline_mk5z6otu4e1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;OK. That, however, doesn&amp;#8217;t explain why when it comes to first person shots of Lara (and by &amp;#8220;shots&amp;#8221; I mean in the sense of photography), the camera is constantly pointing out how big her breasts are. Look no further than this sequence:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/f38f854d723266778e52867f2f05508d/tumblr_inline_mk5za083iV1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/913d7755b8a3aab9645160655050f16e/tumblr_inline_mk5zafPbAt1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/c0ba9f382556814712fe322d88f57992/tumblr_inline_mk5zatWhEa1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Sorry about the first picture, I play with subtitles turned on, even though I write, speak and understand English perfectly. I do the same with films.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;C&amp;#8217;mon, tell me it&amp;#8217;s just not me. You could argue, if you&amp;#8217;re the DP (Director of Photography) because there just has to be one in such a big budget game whose scenery easily produces are stunningly gorgeous shots, that this sequence is simply trying to emphasize on what Lara finds inside the sword. Right! If you&amp;#8217;re a DP, you could also think about it in terms of negative space and then come back to me and tell me what else is there in that scene to look at that&amp;#8217;s not Lara&amp;#8217;s um, well I&amp;#8217;m tired of saying it.&lt;/p&gt;
&lt;p&gt;Of course, you could say me: &amp;#8220;If I were DP I could do a lot worse to get you to look at Lara that way&amp;#8221;. Oh, you mean like this?&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/70672089e989af8925ee17352a1eee47/tumblr_inline_mk5zhk5Nrn1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I&amp;#8217;m going put an to end the argument here. I&amp;#8217;m really not against Lara being beautiful (face), gorgeous (body shape), I&amp;#8217;m simply pointing out the camera isn&amp;#8217;t shy of the fact she&amp;#8217;s not as real as she seems to be. Not all girls could look as good as she does naturally. In the battle of sexes, a lot of guys are portrayed as big and muscular. Now, height is not something we can do much about, but getting in shape is feasible although it might take years; my argument here being if a guy wants to be in shape and enjoy a good-looking muscle structurer, he just has to put in the effort. To girls we&amp;#8217;re simply telling them &amp;#8220;you can get your body to produce a healthily nice figure through hard work, but you either have big breasts or you don&amp;#8217;t&amp;#8221;. As long as nobody here understands we are punishing women for not looking like Lara, that&amp;#8217;s fine by me.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The matter is not over, though. If I thought Lara&amp;#8217;s breasts in the new game were a matter worthy of a couple of paragraphs, you can imagine my shock when in one of the many retrospectives I saw on YouTube I noticed this &lt;a href="http://youtu.be/GZmBdI6TvhU"&gt;not-so-subtle-effect from Underworld&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I mean, WHAT ON EARTH WHERE YOU THINKING, CRYSTAL DYNAMICS!? No wonder the series had fallen into a decay under general perception whilst being tagged as a male titillator. That&amp;#8217;s clearly not realistic and not in the tone of what I thought Crystal Dynamics wanted to do with Lara when they picked up the series. And then you &lt;a href="http://youtu.be/FnUtcOBJgEM"&gt;find Lara dressed in costumes like this, seemingly ready to fight and shoot with any or all of her weapons in her arsenal&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/ca1b0bf89e563e07d5ac695d02f463d0/tumblr_inline_mk5zzaEDHH1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The idea is simply disgusting. But maybe, maybe this speaks even more about what Crystal Dynamics has actually achieved with this new Lara.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;She&amp;#8217;s not only human, she&amp;#8217;s also caring, and most importantly of all, she made me care for the story of how she picked up her first gun and delved into a new world for her.&lt;/p&gt;
&lt;p&gt;The game is so great, I cannot insist in what I said before: this is not about the Tomb Raider of the past, this is about Lara Croft. And keeping in mind how reboots are going lately, I wish a &amp;#8220;Dark Knight&amp;#8221; awaits for us in the future rather than a &amp;#8220;Quantum of Solace&amp;#8221;. Of course, if we do end up in a couple of years with a QoS, it&amp;#8217;ll hopefully be followed by a &amp;#8220;Skyfall&amp;#8221;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a7ae0c42be3e0a903ea41d19ce52299f/tumblr_inline_mk60jiLm3T1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In short, Crystal Dynamics has given a new life to a character belonging solely in the past of video game history. Personally, I&amp;#8217;d rather forget the old Lara existed and just remember that what we have now is an amazing character who discovers herself wrapped in an amazing story as part of the great package that this new Tomb Raider game is.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t know how soon it&amp;#8217;ll be until the next chapter in this amazing reboot arrives, but there&amp;#8217;s one thing I know for sure: not matter what happens in the future, I&amp;#8217;ll always have this Lara to come back. The Lara Croft I chose to remember, the one I choose to keep next to me, forever.&lt;/p&gt;</description><link>http://dinesharjani.com/post/46156599758</link><guid>http://dinesharjani.com/post/46156599758</guid><pubDate>Sun, 24 Mar 2013 09:19:09 -0400</pubDate><category>Gaming</category><category>tombraider</category><category>laracroft</category></item><item><title>El Teide under the snow</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/63a66a68ae95050dab4d0056481442f9/tumblr_inline_mk4ne0s9EG1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m currently more or less under a strict schedule when it comes to my time. This means I dedicate mostly weekdays to push forward on my aspirations such as (fully) picking up iOS development again and becoming comfortable with programming interview questions. But, there are a couple of things I did allow myself to creep into that schedule, like photography, driving, and photography. Not necessarily in that order.&lt;/p&gt;
&lt;p&gt;The last time one of the most iconic views of the Canary Islands and Spain in general got completely covered in snow was in February of 2012. I was here with you at the time, but &lt;a href="http://dinesharjani.com/post/18039487052/iphoneography"&gt;not into photography in DSLR format&lt;/a&gt;. Snow came again this February, but my schedule wasn&amp;#8217;t exactly ready to take a 1-day hit like that, so I stayed at home. However, this very same month (yeah&amp;#8230; like &lt;a href="http://dinesharjani.com/post/41622307701/the-relentless-month-of-gaming"&gt;nothing&amp;#8217;s been happening&lt;/a&gt; &lt;a href="http://dinesharjani.com/post/45600386706/thoughts-on-starcraft2-heart-of-the-swarm"&gt;this month&lt;/a&gt;, and more) it happened again. And even though I was promised it&amp;#8217;d happen again, I didn&amp;#8217;t take the chance and went.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;span&gt;That happened on a Wednesday. I came home that very same day, having driven many hours and taking pictures to more things than just the white mountain (&lt;/span&gt;&lt;a href="#mce_temp_url#"&gt;the Mercedes SLR McLaren&lt;/a&gt;&lt;span&gt; in daylight). The feeling I had is that people &lt;/span&gt;&lt;span&gt;(namely, my friends) &lt;/span&gt;&lt;span&gt;might want to see those pictures. So I went ahead and on Wednesday night quickly (er&amp;#8230; 30 minutes minimum) edited one and posted it. Success.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/08f873920ac1e0279c218e00e4d2b6ee/tumblr_inline_mk4np9d00J1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I got a little bit hooked, if I can admit that. So I kept going the next day. There was actually a picture I really, really wanted to do; it even made me stop at a spot I wasn&amp;#8217;t really expecting to do so and in consequence took this picture almost by accident:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/4f3f76d511d644231127649c0db3089c/tumblr_inline_mk4nu39yWe1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Funnily enough, I describe it as an &amp;#8220;accident&amp;#8221; because I was forced to take that angle because I wanted to portray the snow and because right underneath where the frame ends there were a lot of people goofing around with some remnants of snow. Now that I think about it, shooting that wouldn&amp;#8217;t have hurt either. Anyway, at this point I&amp;#8217;d taken out my 50mm f1.4 and swapped in the classic 18-135mm f3.5-5.6 kit lens, which although we all agree isn&amp;#8217;t as good looking and feeling as my prime, it&amp;#8217;s quite saved by the marvels of HDR photography bringing out details we couldn&amp;#8217;t even notice were there.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/90777d7b2857433a8313c8409a9b0514/tumblr_inline_mk4npqyyUX1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Yup. Like how that one turned out. However, it all isn&amp;#8217;t as perfect as it seems: the image is actually a bit blurry when you zoom into the rocks. Why? Because the wind was so strong my aluminium tripod couldn&amp;#8217;t stand still enough.&lt;/p&gt;
&lt;p&gt;Nevertheless, I know present you the picture I really wanted to take:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/86b311af20249b22c761817cd0c0414a/tumblr_inline_mk4o0qGRnf1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s the view I really, really, really liked. However, I just didn&amp;#8217;t feel it when it came to editing it. It just didn&amp;#8217;t seem &amp;#8220;fulfilling enough&amp;#8221;. It&amp;#8217;s not reasonable and it&amp;#8217;s not entirely logical, but I didn&amp;#8217;t like going down that road. The view of the clouds crashing into that snowed ladder needed a little bit more context. So I picked up a wider view I had, showcasing much better the impact of the snow with the Sun falling down. It almost seems like Mars:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/6efaa69e7f4a1021fb549982353b4f63/tumblr_inline_mk4nq7GRKW1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;Yup, that&amp;#8217;s one I really like.&lt;/p&gt;
&lt;p&gt;There were more, of course. Many more. However, keeping up with the previous three days, I had to focus on a picture I really liked or I wouldn&amp;#8217;t have been motivated enough to continue, so I just focused on that picture of Mount Fuji (or similar) that Apple has in OS X with the mountain covered in snow and lit pink by the falling Sun, and took one I thought would look spectacular and set out to achieve something similar. Here it is:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/4be747b83cbecca32c2ef6fcc17f8561/tumblr_inline_mk4nqrzyJM1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It was not HDR&amp;#8217;ed, contrary to the previous three. There are, of course, many filters and effects applied, and although I&amp;#8217;m happy with the upper and bottom portions of the screen, I&amp;#8217;m not with the middle, which got completely lost (it&amp;#8217;s all pitch black) to provide that effect. Perhaps I should&amp;#8217;ve worked on an HDR version of the view (I did get all the exposures) but, what&amp;#8217;s done is done, and I prefer to keep it as a reminder of a mistake I made.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s just so many pictures I could edit&amp;#8230; let&amp;#8217;s get to it slowly.&lt;/p&gt;</description><link>http://dinesharjani.com/post/46094237347</link><guid>http://dinesharjani.com/post/46094237347</guid><pubDate>Sat, 23 Mar 2013 15:30:07 -0400</pubDate><category>photography</category><category>ElTeide</category><category>CanaryIslands</category><category>Tenerife</category><category>nikon</category><category>snow</category><category>HDR</category></item><item><title>About the Polytron Machine and the Endianness Problem</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/65ecd619f3d80c9124f5ff82dda220df/tumblr_inline_mjxjqivqbV1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;This is going to be a bit of a long introduction, so please bear with me. While following tutorial 3.5 of &lt;a href="http://www.raywenderlich.com/store/ios-5-by-tutorials"&gt;Ray Wenderlich&amp;#8217;s wonderful iOS tutorials&lt;/a&gt;, I hit a point where I needed images in my iOS Simulator. Easiest solution? Open Safari in the Simulator and start &amp;#8220;saving images&amp;#8221;. To accomplish that, I hit one of my daily sites, &lt;a href="http://arstechnica.com/"&gt;Ars Technica&lt;/a&gt;, and stumbled upon a &lt;a href="http://arstechnica.com/gaming/2013/03/get-excited-brain-bending-platformer-fez-finally-coming-to-steam-and-os-x/"&gt;recent article on Fez&lt;/a&gt;. I did get a picture out of that article, but the best part was really watching the video. &lt;/span&gt;&lt;a href="http://youtu.be/2C7Bykq1Wh0?t=2m58s"&gt;Please do it&lt;/a&gt;&lt;span&gt;; I cannot spoil it for you.&lt;/span&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;I mean&amp;#8230; it&amp;#8217;s REALLY cool!!!&lt;/p&gt;
&lt;p&gt;Spoiler alert if you haven&amp;#8217;t seen it yet!!!&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a89dcb52334f058441b58e11131a72e9/tumblr_inline_mjxjsw36CN1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/05b3e504f341c1e1a8a390e1954f0989/tumblr_inline_mjxjseRAJr1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/04611ac236347d9a37fbaf8ead88d35f/tumblr_inline_mjxjrvhLqw1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;I mean&amp;#8230; when I read about the &amp;#8220;reboot&amp;#8221; thing I just had to check it out for myself, even if I was busy actually doing some coding and have a strict policy for not falling off into distractions, which can easily break your &amp;#8220;flow of work&amp;#8221; and kill the chance of you being able to do anything productive.&lt;/p&gt;
&lt;p&gt;But it&amp;#8217;s SO WELL DONE. I mean, you start seeing those glitches in the screen going on so quickly and you think &amp;#8220;yeah, it&amp;#8217;s the game, it&amp;#8217;s just a trick&amp;#8221;. But suddenly everything comes to a halt, and the sound gets &amp;#8220;stuck&amp;#8221; just like it used to do in the old Sony PlayStation when the game crashed, or even in my old PC when a game died mid-session in Windows leaving the Redmond-born OS recovering painfully slowly, with the screen recovering first, and the sound later.&lt;/p&gt;
&lt;p&gt;Honestly, though? What really made put up Fez as a statement of how games carry through the voice and personality of their creators is what comes right next&amp;#8230; the Polytron Machine!!!&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/b09ee475845b921a2ee4155acd39457b/tumblr_inline_mjxk74yrPM1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Wow. That almost took me back to the days of DOS. Seriously, 640Kb of memory? And a 23Mhz CPU? Wonder what architecture it&amp;#8217;s running on. &amp;#8220;press Alt+F2 to enter FISH utility&amp;#8221;. This guy is a legend.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After that, Fez turns into the 2D/3D hybrid it&amp;#8217;s known for, the one I discovered in a little film called &lt;a href="http://buy.indiegamethemovie.com/"&gt;&lt;em&gt;Indie Game: The Movie&lt;/em&gt;&lt;/a&gt;; film which, if I&amp;#8217;m honest with you, I regret not putting my own money into when I first heard about a thing called &amp;#8220;Kickstarter&amp;#8221;, and which I have a new desire to re-watch in its entirety.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/fe65f6dd414bf365334321b8a4c864c2/tumblr_inline_mjxkbwyJDL1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a9f4e38e3bb8c4637f5f0eedebd954b8/tumblr_inline_mjxkcaK1jx1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Let&amp;#8217;s just hope it comes to the Mac very quickly, please.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Onto the second half of this post: &lt;strong&gt;&lt;em&gt;endianness&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The last problem of a &lt;a href="http://www.amazon.com/Programming-Interviews-Exposed-Secrets-ebook/dp/B008SGNJOW/"&gt;well-known book desired to get you as prepared as possible for a tech programming interview&lt;/a&gt; is about a quality hidden inside all modern CPUs which ends up not being very important nowadays (in fact, you could completely forget such a thing exists and have a successful career as a developer in your specific area/field of work), but which turns out to be a pretty interesting question for potential candidates of top-tier tech companies as it involves a very simple problem requiring the use of basic boolean arithmetic and making use of logic; no specific frameworks or languages involved, just plain problem-solving using the foundations of what powers Computer Science. First though, I&amp;#8217;ll answer the question: &amp;#8220;what is the endianness of a CPU?&amp;#8221;&lt;/p&gt;
&lt;p&gt;In short, it&amp;#8217;s very simple. It reflects how a CPU writes numbers: whether it&amp;#8217;s left to right (BIG-endian) or right to left (little-endian). And yes, it only and exclusively relates to numbers, but because numbers are pretty much everything when it comes to assembly code, the one most directly understood by a CPU, it lies at the heart of potential problems when different CPUs with different endianness interact. After all, if I read and write left to right, and you read &amp;amp; write right to left, even though we&amp;#8217;re both speaking in English, none of us will understand each other; we need to translate the other&amp;#8217;s writing (transpose, to be precise) first.&lt;/p&gt;
&lt;p&gt;This simple diagram from Wikipedia might help:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/ab1e87d817f22839e54dc18988bdfd9c/tumblr_inline_mjxmg0MAcd1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;My point being? Back to the book, I obviously tried to write a solution on my own, before hitting a flawed assumption which didn&amp;#8217;t allow me to find it. Out of ideas, I looked at the answer and found out it was the one I&amp;#8217;d thought about before my flawed assumption stepped forward. The code in question is very similar to this one, (if not the same, I just wrote it on my own for testing) since the basic strategy is correct:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/4db605a01d360509f2c129d8d8458e42/tumblr_inline_mjxkwzdmJ41qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;As you can see, we simply put a &amp;#8220;1&amp;#8221; in a register/memory address, get an address to its lowest byte (there&amp;#8217;s always a first and a last word in a sentence, no matter in which direction you write) and then perform a bit-wise AND operation comparing the lowest byte with another &amp;#8220;1&amp;#8221;. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;At first, I thought this code would end up being wrong, because I thought it relied on the fact the second &amp;#8220;one&amp;#8221; would be AND&amp;#8217;ed in a different way as the first one to detect whether the first bit (there&amp;#8217;s always a first character to every word) is a zero or not (leave what that means for later). Why? Because I thought that code led to comparing &amp;#8220;10000000&amp;#8221; in the BIG-endian case and &amp;#8220;00000001&amp;#8221; with &amp;#8220;00000001&amp;#8221; in the little-endian case. It doesn&amp;#8217;t, of course. I tested what happened if you compared &amp;#8220;00000001&amp;#8221; with &amp;#8220;00000001&amp;#8221; and &amp;#8220;10000000&amp;#8221; with &lt;span&gt;&amp;#8220;10000000&amp;#8221; and sure enough, there&amp;#8217;s also a difference in the first bit (lowest address) of the number resulting from the AND operation. Might sound stupid now, but it really wouldn&amp;#8217;t when your mind moves slower than a turtle during a live interview. By the way, it&amp;#8217;s best if you do this yourself on paper; it&amp;#8217;ll become clear.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The meaning? If both first bits are &amp;#8220;1&amp;#8221;s (AND operation is true), then it is a little-endian machine; if both are zero, (AND operation is false), it&amp;#8217;s a BIG-endian machine.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;(If you too have trouble remembering which is which sometimes, use this: little-endian means the &lt;em&gt;least&lt;/em&gt; significant bit is in the &lt;em&gt;least-highest&lt;/em&gt; memory address).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I was actually hoping to use this code for comparison between maybe my (x86) Mac, the iOS Simulator (runs x86 code), my iPhone (ARM) and an Android emulator (translates ARM instructions to x86 for execution). The problem? Even though ARM chips started being BIG-endian, they&amp;#8217;re actually bi-endian these days, meaning they can switch from being little-endian to big-endian at our command. In practice though, Android, iOS and WP8 devices all use little-endian as their form of numerical representation, so that&amp;#8217;s off.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;But that doesn&amp;#8217;t mean there aren&amp;#8217;t interesting questions to ask. For example, &lt;strong&gt;&lt;em&gt;is there any other way of solving this? How about doing this in Java?&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Before actually checking again the book&amp;#8217;s solution worked, another (easy) way became clear to me: set a variable to &amp;#8220;1&amp;#8221;, and perform a left shift by one bit. It&amp;#8217;s a left shift, so no sign extension is involved, and the solution is pretty obvious. &amp;#8220;10000000&amp;#8221; becomes absolute zero, and &amp;#8220;00000001&amp;#8221; becomes &amp;#8220;00000010&amp;#8221;, so a simple test of &amp;#8220;bigger than zero&amp;#8221; answers the question of whether the CPU is little-endian or not. And you cannot point to an integer in the stack in Java, since references only exist with Object(s), so that&amp;#8217;s a clean (and perhaps original) way to answer that question.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Then one last question came to mind: &amp;#8220;&lt;strong&gt;&lt;em&gt;both Intel and AMD CPUs understand the same set of instructions. Supposing AMDs were BIG-endian, could code compiled for one be used in the other and vice versa?&lt;/em&gt;&lt;/strong&gt;&amp;#8221;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Yeah&amp;#8230; stupid and at the same time a bit far-fetched. But I answered my own question, and it&amp;#8217;s a &amp;#8220;no&amp;#8221;, and the answer is simple: &amp;#8220;00000001&amp;#8221; is not the same instruction as &amp;#8220;10000000&amp;#8221; (yes, I know that in two&amp;#8217;s complement the latter is a negative number, but it&amp;#8217;s a pointless fact here), so the resulting program would not be the same &amp;#8220;program&amp;#8221; if little-endian code were executed in a BIG-endian machine or vice versa. Think of it this way: the sequence of numbers &amp;#8220;1&amp;#160;2 3&amp;#160;4 5&amp;#8221; is not the same as &amp;#8220;5&amp;#160;4 3&amp;#160;2 1&amp;#8221;; even though they&amp;#8217;re the exact same numbers written in a different way, they have totally different meaning. One is &amp;#8220;numbers 1 to 5 in ascending order&amp;#8221;, and the latter happens to be its exact opposite. I guarantee you instruction &amp;#8220;1000000&amp;#8221; has nothing to do with &amp;#8220;000000001&amp;#8221; in an 8-bit CPU, and much less in a modern ARM or x86 chip.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Had enough? I think so :) I just wanted to try something I&amp;#8217;ve been telling myself for a few months, which is including &amp;#8220;developer stuff&amp;#8221; in my blog. Hope you had some fun, and please feel welcome to correct me if you think I&amp;#8217;ve said something wrong!&lt;/span&gt;&lt;/p&gt;</description><link>http://dinesharjani.com/post/45794885609</link><guid>http://dinesharjani.com/post/45794885609</guid><pubDate>Tue, 19 Mar 2013 20:08:00 -0400</pubDate><category>Gaming</category><category>indiegames</category><category>indiegaming</category><category>fez</category><category>philfish</category><category>polytron</category><category>C</category><category>endianness</category><category>cpu</category><category>processors</category><category>littleendian</category><category>bigendian</category><category>iOS</category><category>Android</category><category>C++</category><category>development</category><category>programming</category></item><item><title>Thoughts on Starcraft II: Heart of the Swarm</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/78752fbe7411678492b0fbaf6aa2a073/tumblr_inline_mjtb205G941qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;The day finally arrived, and passed before I could even realize it was all over again. Last weekend I forced myself into doing studying extra in order to do something I&amp;#8217;d never done before: hit a game the second it launched. And the game worthy of such an honor? It could only be Starcraft II&amp;#8217;s first expansion.&lt;/p&gt;
&lt;p&gt;Unlike its predecessor, I started playing the game mere seconds after it&amp;#8217;d come online, past 11pm of my Monday, March 11th 2013. It just seemed so unreal; I could not believe I was really playing the game, that the story was unraveling right in front of me, and that just as I wanted, I stayed as far away as I could from the &amp;#8220;Hollywood trailer&amp;#8221; which I had the pleasure to see after going through the game&amp;#8217;s credits. And sure enough, it was full of spoilers, containing images from the last cutscene of the game. Glad I kept myself from that. In Blizzard&amp;#8217;s defense though, it was a trailer worthy of a Hollywood film. It really was. Or is. But I wanted the complete &amp;#8220;Starcraft&amp;#8221; experience, just like I&amp;#8217;d experienced it back in 1999, 2000 and 2001 when the original game and expansion became part of the fabric of my existence; being one of the first games I overcame my cheating addiction and focused on getting through the old way: by learning and adapting my playstyle. (I did not reach the end of the original game without cheats and cheated my invincibility all the way through the &lt;em&gt;Brood War&lt;/em&gt; expansion. Oops.) But it was more than that.&lt;/p&gt;
&lt;p&gt;The story, the characters, the drama, the universe. It was just so perfect. It wrapped everything up, and it left no holes nor ties unattended. It seemed so orchestrated, so &amp;#8220;planned&amp;#8221; yet undiscovered. It was the perfect blend of being surrounded by an environment you enjoy to the very last drop, the space opera, but at the same time, immersed in a set of conditions where you really couldn&amp;#8217;t predict what would happen next: you sat there and were simply thrown from side to side as the story built itself around its characters and about all of those things lurking in the shadows you just wish you could know more about.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;em&gt;Starcraft&lt;/em&gt;, as you know, was partly &amp;#8220;abandoned&amp;#8221;. And I say partly because it really wasn&amp;#8217;t; the team behind &lt;em&gt;Warcraft&lt;/em&gt;, &lt;em&gt;Warcraft II: Orcs &amp;amp; Humans&lt;/em&gt; made &lt;em&gt;Starcraft&lt;/em&gt;, &lt;em&gt;Starcraft: Brood War&lt;/em&gt;, and then followed with &lt;em&gt;Warcraft III: Reign of Chaos&lt;/em&gt; and its expansion, &lt;em&gt;The Frozen Throne&lt;/em&gt;. Then, the team went silent, and we didn&amp;#8217;t know much about them. Blizzard became the &amp;#8220;Apple&amp;#8221; of the gaming community harnessing all the money in a business no one had ever really understood, MMOs, and this great franchise called &amp;#8220;Starcraft&amp;#8221; was left behind with unsuccessful stories like &lt;em&gt;Starcraft: Ghost&lt;/em&gt;, which did result in a worthy character for the canon: Nova Terra (who&amp;#8217;s a total b****, by the way!!! Play HoTS first if you want to know why). It was in 2007 when Blizzard revealed the truth: the team behind their successful RPGs had begun working on SCII right after &lt;em&gt;The Frozen Throne&lt;/em&gt;, but got delayed by 1-2 years to help the WoW team get their money-making machine out of the door. April/May 2007. Until July 2010 the game wouldn&amp;#8217;t hit the shelves. And I played it on the following month of December.&lt;/p&gt;
&lt;p&gt;11:01pm of March 11th, 2013: &lt;em&gt;Heart of the Swarm&lt;/em&gt; arrived. And it just couldn&amp;#8217;t have been better. And the best way of looking at it is by focusing on the first campaign of the Starcraft II arc: &lt;em&gt;Wings of Liberty&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/5bbd783744871d3b2d0250307fe64e84/tumblr_inline_mjtfylGSzM1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Wings of Liberty&lt;/em&gt;&lt;span&gt; brought the Starcraft world back into our era. Its addictive gameplay, where as ridiculous as it sounds, you just can&amp;#8217;t have enough of the &amp;#8220;build your structures, ramp up the economy, get an army, crush your rival&amp;#8221; formula. On paper it might just look like doing the same again and again, but it just isn&amp;#8217;t, and you&amp;#8217;re constantly anticipating when will the next mission be. The game itself, its campaign, transported into our era the story, the world, the universe I&amp;#8217;ve loved and kept close to my chest, making it as real as it&amp;#8217;s ever going to get. And focusing back to the story and the game&amp;#8217;s mechanics to push it forward, I always felt like the story&amp;#8217;d been a bit held back. Maybe it was the fact that I already knew what the game was about and had seen the &amp;#8220;Hollywood trailer&amp;#8221; of the title, but the sequences, the conversations and the scenes always felt a bit &amp;#8220;honed in&amp;#8221;. Don&amp;#8217;t get me wrong: it all fits nicely together from the outside, but it just wasn&amp;#8217;t as smooth as you&amp;#8217;d like it to be, as you know it could be, while playing it through. But the story did move forwards, only not as much as I&amp;#8217;d hope. The game itself is insane fun, since you can&amp;#8217;t stop doing mission after mission because you don&amp;#8217;t really know what it&amp;#8217;s going to be about until you actually click on it and it starts. You might be in the midst of a story arc, but you don&amp;#8217;t really know what the action&amp;#8217;s going to be until it starts, and Blizzard hand-crafted a game that really doesn&amp;#8217;t make it feel like the formula is repeated or like the playthrough is excessively linear, because there&amp;#8217;s just so many things to do, and everyone plays differently. Plus, we were the terrans!! &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;All in all, the story was good, it had an incredible ending, one that took us back to the drawing board saying, once again (like at the end of &lt;em&gt;Brood War&lt;/em&gt;): &amp;#8220;now what?&amp;#8221;, but I felt like more things could&amp;#8217;ve happened in the same amount of time / missions. &lt;/p&gt;
&lt;p&gt;Enter &lt;em&gt;Heart of the Swarm&lt;/em&gt;, where the addictive formula is kept in every corner of the title&amp;#8217;s gameplay, and where in the campaign mode, story is everything. Right from the start, where I couldn&amp;#8217;t help but say: &amp;#8220;oh, Blizzard. You&amp;#8217;re just too good.&amp;#8221; at the so-called &amp;#8220;Prologue&amp;#8221; teaching you how to play the most disgusting race ever, the Zerg (really; I could swear as a kid looking at their structures evolve I felt like vomiting), the game and its playthrough are all about rightfully serving the story, and it does advance at a pace I&amp;#8217;m a lot more comfortable with. It&amp;#8217;s like going from visiting planet to planet and just sitting in the Hyperion&amp;#8217;s bridge to swimming on the Spawning Pool of every Hive cluster you build (nice analogy, right?). The game just delivers sooo much more, and when it comes to cinematics, I honestly couldn&amp;#8217;t really make out the difference sometimes. And when it comes to count, HoTS just blows WoL off the water then it comes to real CG. I don&amp;#8217;t have a rea estimate, but WoL only had three pre-rendered cinematic sequences not counting the intro, and HoTS has a lot more, just as it should. &lt;/p&gt;
&lt;p&gt;I was beginning to wonder whether they&amp;#8217;d become just too difficult (or costly) for Blizzard to make them. But thankfully Blizz let all my doubts to rest with this title.&lt;/p&gt;
&lt;p&gt;In short: the campaign is insanely good. I never thought I&amp;#8217;d have this much fun playing the Zerg; in fact, I had doubts I could even fathom getting through the whole game playing my least favourite race, but Blizzard gave me more than enough reasons to do so, and I just couldn&amp;#8217;t have enough of it. And like all good things, it came to an end yesterday.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/03a3adc615ff930c8d19c0a10e4bfa37/tumblr_inline_mjtg85hpje1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Into the next topic: reviews. While YouTube loaded every available video of the Behind the Scenes DVD bundled with the physical Collector&amp;#8217;s Edition of the game, I started going through all the available reviews (just like with Doom 3: BFG Edition, Polygon has not written one. I wonder why?) and spotted a common trend: HoTS is being considered worse than WoL. The main concern with the story is that it follows many clichés, which in some ways is true: it&amp;#8217;s probably the first bit of &lt;em&gt;Starcraft&lt;/em&gt; canon I&amp;#8217;ve encountered which doesn&amp;#8217;t totally shatter the rules of everything I&amp;#8217;ve read before, but somehow, I&amp;#8217;m not mad at Blizz, because it all simply fits. Critics keep that &lt;/span&gt;&lt;em&gt;Wings of Liberty&lt;/em&gt;&lt;span&gt; was simply too good of a game, that they enjoyed their campaign far more, and that HoTS tries to be a soap opera fuelling a love interest (Jim - Sara) with no grounds. Well, I just can&amp;#8217;t be on your side.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;(Spoiler alert!: some plot details follow)&lt;/p&gt;
&lt;p&gt;To begin with, I was also taken by surprise at Jim&amp;#8217;s love for Sara at the game&amp;#8217;s opening, since we hadn&amp;#8217;t ever seen it before. But at the same time, this seed had been planted for us in the conversation of the Battle for New Gettysburg, where &amp;#8220;Jimmy had to drop the knight-in-shining armor&amp;#8221;, and then in distinct parts of the story where Sara called to Jim to rescue her while inside the Chrysalis, when the Queen of Blades never even thought about killing Raynor after finishing off both General Duke and Fenix once Korhal fell once again in Arcturus&amp;#8217; hands (yup, this is a pretty big story) after the UED took it from him, and again during &lt;em&gt;Wings of Liberty&lt;/em&gt; where we could see how Jim couldn&amp;#8217;t stop feeling the blame for all of Kerrigan&amp;#8217;s actions after that dreadful day in which Arcturus &amp;#8220;signaled the fleet out of orbit&amp;#8221;. Granted, Kerrigan does come at us in a pretty fierceful way toward the end of WoL, but it could be argumented that she was only protecting herself and the Swarm. She didn&amp;#8217;t really ever threat Jim in person.&lt;/p&gt;
&lt;p&gt;No. To me, there&amp;#8217;s clearly a lot of story not told here. And what if these two where always in love, behind the scenes, but we just didn&amp;#8217;t know about it until HoTS made it pretty clear? This is just a clear example of how some critics never gave the game a chance.&lt;/p&gt;
&lt;p&gt;Wait. There&amp;#8217;s more. Bad dialogue!? Are you kidding me&amp;#160;!!?? Robert Clotworthy, James Harper and Tricia Helfer are incredible in their voice acting, not to mention the incredible range of Zerg monsters with their distinct habits. The most annoying creature for me was Dehaka, because he spoke far too slowly, and I like to play with subtitles on. (Any problem?) I loved Abathur, though. And yes, I also thought about his similarity to speaking lady-parts, but mostly succeeded at thinking of him as a vile Zerg creature who snapped Kerrigan&amp;#8217;s arms and limbs to make her more &amp;#8220;effective&amp;#8221; during her careful growth inside the (first) Overmind&amp;#8217;s Chrysalis. &lt;/p&gt;
&lt;p&gt;Speaking of Overmind(s): I really misunderstood the game and thought Amon was the first Overmind. He&amp;#8217;s clearly not. But I can&amp;#8217;t make out if he&amp;#8217;s the &amp;#8220;Dark Voice&amp;#8221; or not. Is he?&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/e460db811e43e7cf65351bce794d3ea8/tumblr_inline_mjtfb9lBW71qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;One last thing. Kerrigan is absolutely, insanely beautiful. She&amp;#8217;s incredibly gorgeous. I really don&amp;#8217;t know how the Starcraft II game engine made her look this good, but she beats Lara Croft in the new &lt;/span&gt;&lt;em&gt;Tomb Raider&lt;/em&gt;&lt;span&gt;, which I&amp;#8217;ll get back to as soon as I finish writing this piece. &lt;a href="http://dinesharjani.com/post/41622307701/the-relentless-month-of-gaming"&gt;Month of relentless gaming&lt;/a&gt;, remember?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And just like that, here we are. Back at the end of the road. For me, &lt;em&gt;Starcraft&lt;/em&gt; is not &amp;#8220;just a game&amp;#8221;; it&amp;#8217;s something that goes far beyond that, and I can&amp;#8217;t fully explain it in words. It&amp;#8217;s been a sort of anchor in my life, and every time a new one comes out (namely, these last two times), I tend to look back and use it as a reference of my own personal evolution, and look at how my life and my own self has changed ever since the last time it came out. I understand that for most people it won&amp;#8217;t be the same, but I feel like this when it comes to &lt;em&gt;Starcraft&lt;/em&gt;. I wish I could continue the story right now and keep going on, finding out what&amp;#8217;s Zeratul&amp;#8217;s take on the story, and what happened with that Zerg (Alien!) infested Zerg Protoss ship which we last saw en route to Shakuras, and how the Protoss government judges his actions, but a part of me knows that&amp;#8217;s not what I really want. What I really want is start distancing my own self from the current one that has just lived through this first expansion and set the bar own higher for when I look at myself again upon the arrival of &lt;em&gt;Legacy of the Void&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;By the way, if you ask me, don&amp;#8217;t expect it until the 2015 Christmas season, but I&amp;#8217;m more inclined towards a summer 2016 release of the final chapter in the Starcraft II story arc.&lt;/p&gt;
&lt;p&gt;For sure, the game won&amp;#8217;t abandon me completely, having &lt;a href="http://www.youtube.com/user/HuskyStarcraft"&gt;discovered Husky as my favorite caster in YouTube&lt;/a&gt; since 2011, but now it&amp;#8217;s not the time to look back and marvel at all the delicious feelings this story and characters take me through. It&amp;#8217;s time to build the next segment of the highway to my dreams; the one I only have time to build until &lt;em&gt;Legacy of the Void&lt;/em&gt; comes around.&lt;/p&gt;</description><link>http://dinesharjani.com/post/45600386706</link><guid>http://dinesharjani.com/post/45600386706</guid><pubDate>Sun, 17 Mar 2013 13:57:00 -0400</pubDate><category>Gaming</category><category>Starcraft</category><category>heartoftheswarm</category><category>hots</category></item><item><title>The Closeness of Social Media</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/ac5abc9acb6e6c239a8441c6d5f58918/tumblr_inline_mjcg7apa0a1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Up to this point you must be like&amp;#8230; &amp;#8220;OMG! Where has this guy gone again!?&amp;#8221;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Well, I&amp;#8217;m not gone, not entirely anyways. Still trying to move forward with publishing a lot more about my photography, and I&amp;#8217;ve got a lot of interesting things coming your way, but for now, I&amp;#8217;ll keep posting final images to both &lt;a href="https://twitter.com/dinesharjani"&gt;Twitter&lt;/a&gt; and &lt;a href="https://plus.google.com/116144720450951794613/posts"&gt;Google+&lt;/a&gt; and I&amp;#8217;ll hopefully come here and as always give you a much better view about what goes on in the sidelines.&lt;/p&gt;
&lt;p&gt;As you know though, this has been the week of the new Tomb Raider. I&amp;#8217;m heavily anxious about the new Starcraft 2 expansion though, and this one comes right after. But, that doesn&amp;#8217;t mean I haven&amp;#8217;t been paying attention to all things being said about this game; after all, &lt;a href="http://dinesharjani.com/post/24841850670/a-very-welcome-reboot"&gt;I&amp;#8217;ve been following it literally since day one&lt;/a&gt;. What surprised me though, is the actress behind Lara Croft herself, Camilla Luddington.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;You see, the end of 2012 and the beginning of 2013 has been full of remarks about whether technology companies investing in celebrities really pays off or not; you&amp;#8217;ve got the case of &lt;a href="http://www.dailymail.co.uk/sciencetech/article-2235736/Oprah-Winfrey-tweets-love-Microsofts-Surface--using-iPad.html"&gt;Oprah Winfrey &amp;#8220;defending&amp;#8221; Microsoft whilst tweeting from an iPad&lt;/a&gt;, &amp;#8220;&lt;a href="http://www.theverge.com/2012/11/28/3699182/how-twitter-is-ruining-the-celebrity-endorsement"&gt;Call Me Maybe&amp;#8221; star Carly Rae Jepsen use a Lumia 920 on her videos but using an iPhone for her day-to-day tweets&lt;/a&gt;&amp;#8230; There are many examples, these are just coming off the top of my head. So when I encountered Miss Luddington&amp;#8217;s (who&amp;#8217;s absolutely gorgeous, btw!) Twitter timeline for the release of the new Tomb Raider, I was stunned at her campaign.&lt;/p&gt;
&lt;p&gt;It has always been said that Social Media is not about pretending to be someone you&amp;#8217;re not, because like in real life, it comes back to bite you, and because people already know what sort of &amp;#8220;character&amp;#8221; you&amp;#8217;re playing, t&amp;#8217;s boring, and they know what to expect. Instead, the right way to do it is to just be you; as simple as that. You must express all of the quirkyness you might have inside you, because it makes you unique, it makes your personality transcend barriers, it makes people &amp;#8220;connect&amp;#8221; to you, making them feel like they&amp;#8217;re next to you, even when they&amp;#8217;re not.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/f9a256afb3d1f8ce0eaa8933e601313b/tumblr_inline_mjcgmrTl5E1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;This image here, represents exactly that. Camilla Luddington portrays Joanna Wilson in the renowned series &lt;em&gt;Grey&amp;#8217;s Anatomy&lt;/em&gt;, and by showing us pictures like this one, she turns reality of a day-to-day experience into a window we can all look into and get a breath of what her life looks like. She&amp;#8217;s watching someone play her game dressed as Joanna Wilson in the &lt;em&gt;Grey&amp;#8217;s Anatomy&lt;/em&gt; set, and she posts it like a normal person just enjoying her job. The customized XBox and the game are clearly visible, granted, but the image isn&amp;#8217;t built from the ground up in a studio; it&amp;#8217;s just her, sharing a moment.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So many times you look through the eyes of a famous celebrity you get the chance of putting in your living room for about 30 hours a year and you always wonder whether they&amp;#8217;re real or not, whether they&amp;#8217;re &amp;#8220;people&amp;#8221; or not, and breaking the barrier with informal moments like this is just how you get the general audience to feel like something&amp;#8217;s real; whether it&amp;#8217;s a brand, a game, a person, a set or a TV Show. She just nailed how to promote herself in a very natural and believable way.&lt;/p&gt;
&lt;p&gt;Thankfully, those two were not the only &amp;#8220;gifts&amp;#8221; she&amp;#8217;s left on Twitter:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a1c4fd8171b9bd5fc8bc2349ce59c292/tumblr_inline_mjcgutbFDl1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/2409b87f127199338c7607f163ce9b43/tumblr_inline_mjcgv3VCrB1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/696fc99cef4bb56c21b8454bf7427b56/tumblr_inline_mjcgvgeVxy1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;She is not selling b***shit about the game, she&amp;#8217;s just acting like any normal 20+ girl would do upon receiving a set of games and controllers after three years of hard work: taking a picture of her prize (making all the mistakes a normal person would, not noticing her own reflection in the mirror) and letting all of her &amp;#8220;gals&amp;#8221; (in this case, Twitter followers) know about it. She even has a convincing image of a coworker about to fall off her chair while playing the game.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Really, if she&amp;#8217;s not the personality behind all of this, someone clearly is, and whomever you are, you&amp;#8217;re doing a hell of a good job, and the whole social media industry should watch how it&amp;#8217;s really done.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/53f6af651a11446d504afe88bb8b7b5b/tumblr_inline_mjch4ovnlB1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/dc4f90c364324c661c1fda83a5d36f32/tumblr_inline_mjch51RmYU1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;God bless you, Twitter. Finally they&amp;#8217;re starting to really get you. Now let me get back at ogling this gorgeous brit until Heart of the Swarm is released.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: the source of all these images is &lt;a href="https://twitter.com/camilluddington"&gt;Camilla Luddington&amp;#8217;s own Twitter profile&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</description><link>http://dinesharjani.com/post/44858754219</link><guid>http://dinesharjani.com/post/44858754219</guid><pubDate>Fri, 08 Mar 2013 09:01:58 -0500</pubDate><category>Gaming</category><category>tombraider</category><category>twitter</category><category>social</category></item><item><title>Game Engine
Ok, folks. I’ve got to admit my own share of...</title><description>&lt;iframe width="400" height="300" src="http://www.youtube.com/embed/SvLsOF-c0_0?wmode=transparent&amp;autohide=1&amp;egm=0&amp;hd=1&amp;iv_load_policy=3&amp;modestbranding=1&amp;rel=0&amp;showinfo=0&amp;showsearch=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Game Engine&lt;br/&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ok, folks. I’ve got to admit my own share of fault regarding “letting you a bit down lately”. I’ve barely worked on my pending photography work, trying to split my focus every weekday in both re-mastering (to some extent) the nuts and bolts of iOS and in studying some books, like &lt;a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X"&gt;this one&lt;/a&gt; or currently &lt;a href="http://www.amazon.com/Programming-Interviews-Exposed-Secrets-Landing/dp/1118261364/"&gt;this other one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On my weekends, though, I’ve been going off anything that’s been anything similar to “work”, and I have to admit photography is in some ways “work” for me due to the level I try to push myself forward to (of course; you’re the ultimate judge in deciding whether I’m being successful or not). So what’s left? Starcraft. More specifically, its first expansion in years, so I’ve been covering my last two weekends not in photography, but in gaming.&lt;/p&gt;
&lt;p&gt;Kind of rare in me, I have to admit; since the original Starcraft 2 I didn’t enjoy myself playing so much. Of course, what I’m doing right now is simply re-playing the whole campaign to be ready for the story and, as &lt;a href="https://twitter.com/dinesharjani/status/306548354496729089"&gt;you might’ve heard&lt;/a&gt;, I’ve also isolated myself from &lt;a href="http://www.polygon.com/2013/2/26/4032948/starcraft-2-heart-of-the-swarm-vengeance-trailer"&gt;watching the latest trailer&lt;/a&gt; because… well, quite simply, I remember &lt;a href="http://youtu.be/rgyL08nhtkw"&gt;a similar trailer when Wings Of Liberty launched&lt;/a&gt; that spoiled some scenes for me, and I really want to give this game a chance to enchant me, so I’m avoiding it.&lt;/p&gt;
&lt;p&gt;That of course, didn’t stop me yesterday evening from asking myself: “is there any information about Starcraft II’s game engine?” It wasn’t exactly out of the blue; I was ogling &lt;a href="http://www.amazon.com/Game-Engine-Architecture-Jason-Gregory/dp/1568814135"&gt;this book&lt;/a&gt; for cues on C++ performance coding.&lt;/p&gt;
&lt;p&gt;And there you go. Like magic. The video’s from 2011, so some work on HoTS was already underway by that point. Blizzard really is an elite playground for the most highly skilled game developers out there.&lt;/p&gt;
&lt;p&gt;Makes you want to watch &lt;a href="http://youtu.be/1ipBCEZwbM0"&gt;this&lt;/a&gt;, huh? :)&lt;/p&gt;</description><link>http://dinesharjani.com/post/44166907042</link><guid>http://dinesharjani.com/post/44166907042</guid><pubDate>Wed, 27 Feb 2013 17:09:00 -0500</pubDate><category>Gaming</category><category>Starcraft</category><category>HeartOfTheSwarm</category><category>developers</category><category>development</category></item><item><title>How NOT TO post-process a photo (HDR)</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/c43b7c8dd767e6f07775c068ad96dc5a/tumblr_inline_migw6vkJf61qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Okay, so we&amp;#8217;re again back in the photography world, and I want to keep going. There&amp;#8217;s still so much photography work waiting for me in the back-burner, but I feel this is a lesson I should share, too. As you can see above this post&amp;#8217;s cover picture isn&amp;#8217;t anything to talk at home about; it&amp;#8217;s just plain boring. However, for me this building is nothing but boring: it&amp;#8217;s the building that&amp;#8217;s provided me a shelter in which to comfortably study and work time, and time again. And back in September (yes, September) I already knew I wanted to dedicate a special picture to it, so I decided one day I&amp;#8217;d go early, park the car near the entrance (see the cars on the right?), and when the light got low enough, come out, keep my books in the boot and start taking pictures. How innocent of me.&lt;/span&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;I did manage to get some, in fact, but security wouldn&amp;#8217;t let me, after I got close to the entrance, claiming I was taking pictures from within the building&amp;#8217;s property (the small black patch of asphalt outside it). I&amp;#8217;d taken a few, quite a few I&amp;#8217;d say, and they weren&amp;#8217;t allowing me to keep shooting because I needed a &amp;#8220;special permit&amp;#8221; to take pictures in their property, or so the officer said (as a note: he also said taking pictures inside is entirely prohibited because of IP issues with the building&amp;#8217;s architects). Fine; I got the permit, and went down again to shoot even more pictures, but somehow I left feeling the &amp;#8220;good pictures&amp;#8221; where from my first shooting, not from my second.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/36f23d9b486014e2861ee6db311830f1/tumblr_inline_migw5mMjes1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Conversely, I also decided NOT to work on them after being finished; they needed some time, some experience; two things I wasn&amp;#8217;t willing to give since I had more important priorities at the time. Until now, of course. Finally I decided I &amp;#8220;wanted to make mistakes&amp;#8221; with these pictures, and so I did.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/b25d637ea54a68258f474f577c49a3cb/tumblr_inline_migwcemmfd1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;This is our first winner for the evening. And believe it or not (easy to believe: the big streetlight&amp;#8217;s shot of light is burned in the black ground) that&amp;#8217;s an image straight out of the camera, no post-processing involved. It&amp;#8217;s almost flawless: you&amp;#8217;d want the light on the ground not to be burned down, and the library&amp;#8217;s glowing light to be well-measured, too. Easy: I had a much lower-stop HDR shot in my Lightroom library, too. I merged both, did some &amp;#8220;artwork&amp;#8221;, and this was the result:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/7621ad1d43430427ced7de95f8de3201/tumblr_inline_migwfgnpv41qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Yeah&amp;#8230; no wonder none of my friends actually liked it on Facebook. I just went too far: I loved the detail HDR brought to the building, and the sky&amp;#8217;s colors were a lot more intense, plus, the yellow haze from the streetlights was correctly reflected in the ground; I mean, that&amp;#8217;s almost as real as it &amp;#8220;could&amp;#8221; get. But I went too far. Despite that, I just knew the angle and the composition were &amp;#8220;killer&amp;#8221;, so I put it up on Facebook anyway.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;What follows though, is strictly between you and me.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/e6be2a34f0108bdc324544e1930caa5a/tumblr_inline_migwk79pnT1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Next up! After that killer shot, my number two shot reflected the main library&amp;#8217;s beautiful entrance, showcasing the beautiful lighting inside and the particular entrance&amp;#8217;s architectural style. I had many compositions at hand, all with multiple eVs to grant me all the post-processing freedom I could possibly need, and as I found out, all of my first-shooting&amp;#8217;s were downright unusable. This is the first picture you&amp;#8217;re seeing of my second shooting, and while the angles on my first were good, too, the streetlights posed a threat I didn&amp;#8217;t want to deal with in Photoshop, to put simply (they were taken much later in the evening). Plus, I had a very strange sky filled with noise in my best frame and my lens wasn&amp;#8217;t apparently clean enough, so I deemed those shots unrecoverable if I had something better, and I decided &lt;/span&gt;&lt;em&gt;then&lt;/em&gt;&lt;span&gt; that I had from my second field-day. Here&amp;#8217;s the test HDR &amp;#8220;build&amp;#8221; I made to make that decision.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/33ebb98561fd6696317785a6b0fc0c41/tumblr_inline_migwuywcjj1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I agree with you, it&amp;#8217;s beautiful, but if I could, I wanted to avoid myself all that Photoshop work (yes, I know it involves masking and erasing with multiple opacities to soften all of that stuff&amp;#8230; but I just didn&amp;#8217;t want to go there). You can decide later if my final picture is in fact better or not than this one; but that&amp;#8217;s (in part) what this blog is all about: giving myself room to make mistakes and express them.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;With my path chosen, I began work on that virgin shot I just showed you, and here is its first post-FX iteration:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/3a8fb464bd5e1ee27a6fca57c2974496/tumblr_inline_migx16Ysj21qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Having arrived here, I&amp;#8217;d already decided this was NOT a winner. I didn&amp;#8217;t like how the (faked) sunset wrapped the building, and I wanted something better. With a little more work from the start perhaps, it might&amp;#8217;ve been passable: after all, having made that previous (first) mistake, I knew I had to shoot for &amp;#8220;realistic&amp;#8221;, not &amp;#8220;color-candyland&amp;#8221;. But I decided to take my mistake even further, since the picture still didn&amp;#8217;t provide enough of a &amp;#8220;sunsetty&amp;#8221; feel. So I took another pass and post-processed it again. Here&amp;#8217;s the (eye-hurting) result.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/e9c8e15046eeb394912ca39baf23f0e6/tumblr_inline_migx5eK8Sd1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Not what any human being would consider a pretty picture, right? I agree with you.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Since I didn&amp;#8217;t entirely like the frame&amp;#8217;s composition (I liked parts of it, like the fact it reflected the back of the entrance and the red arch behind, like the dusty HDR shot I showed you before), I moved on to another one, this one.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/cf3ff023c60edb3fc48400ebd73f7733/tumblr_inline_migx86Qs2Y1qz4rgp.jpg"/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;You can already tell it was a no-no, right? Oh, my&amp;#8230;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Well, what I liked about this is that it reflected more of the entrance, of its character, and so it became my center of attention. First round?&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a13a3d4dd0c06992f6ef2100ae4ea40e/tumblr_inline_migxachLPH1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The whole post-processing was more integrated with the picture, delivering better tones and colours. However, it was still a bit far on the candyland area: too much detail derived from the HDR process. And I didn&amp;#8217;t like it. Small adjustments didn&amp;#8217;t do it for me, either.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a82d40b8af659184f56cf1775d78bcd8/tumblr_inline_migxchk6p31qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It was decent, ok? Maybe you disagree, but I think it was decent.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Still, that&amp;#8217;s not what I wanted to portray of that building at all. It just wasn&amp;#8217;t, no way. So I had to look further, and my next try turned out to be the winner.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/e46bbaa129545d4fd6e28e4762ba5e27/tumblr_inline_migxfdXGrp1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;But something had to change, because I was doing something wrong. I was still post-processing far too much, and I somehow had to keep the colors inline. My last attempt had proven to be acceptable, but had nothing of the beautiful and calmy feel that building gives me, and again, I wanted it to be a sunset, from the start. So we had work to do.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/c43b7c8dd767e6f07775c068ad96dc5a/tumblr_inline_migxi6zXLF1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;But boy, did it work out this time.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/436668771cfefa4d26e64c66b7d94139/tumblr_inline_migxjeDznG1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;To achieve the sunset effect, I did not rely in any kind of filter, just common sense: I obtained an HDR image, and then set the highlights split tone to the appropriate color; only a few minor corrections were required, and the effect seems natural enough. The end-result is&lt;/span&gt;&lt;span&gt; colourful, not the over-the-top variety of colors that makes you kill yourself, but in a beautiful kind of way instead.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Four of my friends &lt;/span&gt;&lt;a href="https://www.facebook.com/photo.php?fbid=10200434317637385&amp;amp;set=a.4385607235228.2181483.1139670546&amp;amp;type=1&amp;amp;theater"&gt;liked it on Facebook&lt;/a&gt;&lt;span&gt; (five when I used it as my cover picture) and it has provided me with &lt;/span&gt;&lt;a href="http://500px.com/photo/24963991"&gt;my second-highest rated picture in 500px&lt;/a&gt;&lt;span&gt;. I still don&amp;#8217;t think it&amp;#8217;s without its flaws: namely, it would&amp;#8217;ve looked much better without that vignetting, but somewhere in my post-FX chain I agreed to it and I couldn&amp;#8217;t take it back once the end-result was obvious.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Lessons? I need to compare more often my pictures to the originals throughout the HDR stage (if any) and I need to keep the colors balanced, because &lt;em&gt;this is my&lt;/em&gt; HDR style, not the over-the-top one. I have worse HDR-derived pictures (more painting-like) with three-to-four times more &amp;#8220;likes&amp;#8221;, and I&amp;#8217;m starting to really grasp how &amp;#8220;less is more&amp;#8221; in photography.&lt;/p&gt;
&lt;p&gt;I mean, HDR is necessary, at least it feels to me in landscapes, but it has to be subtle, only filling in those lights you&amp;#8217;d miss if we weren&amp;#8217;t talking HDR. Does this really feel HDR to you? No, after all you&amp;#8217;ve seen. No. But it is.&lt;/p&gt;
&lt;p&gt;With this post I want to explain the route I&amp;#8217;m intending to follow after this lesson. Although, of course, I can imagine there might be a question lingering in your mind: &amp;#8220;are you ready to finally fulfill what you once showed us?&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/54a44d067bc01fdbf106710928ec2f59/tumblr_inline_migy0je4Ij1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Definitely hope so. I&amp;#8217;ll let you know the moment I get started.&lt;/span&gt;&lt;/p&gt;</description><link>http://dinesharjani.com/post/43483745929</link><guid>http://dinesharjani.com/post/43483745929</guid><pubDate>Tue, 19 Feb 2013 08:31:00 -0500</pubDate><category>photography</category><category>tenerife</category><category>hdr</category><category>post-processing</category><category>postFX</category><category>nikon</category><category>d80</category></item><item><title>Pyramid at (Fake) Sunset</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/f575f1e359449e1e7d72262c27d63b4a/tumblr_inline_mi61diJs231qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;I thought about working on this picture out of the blue, quite literally. It&amp;#8217;s one of those pristine RAW shots I keep from the trip I took to SF for Google I/O 2011 (with the camera I can now call my own) from a time I knew next to almost nothing about photography. I took this one stopping right on my tracks during a zebra crossing and looking right to face this icon. It&amp;#8217;s one of those pictures that has really stood out for me out of all the shots I took back then, and it suddenly hit me that I could do something about it.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;The first thing I did though, was edit and photoshop the hell out of it, like I&amp;#8217;d been doing during the &lt;a href="http://dinesharjani.com/post/40942589165/2013"&gt;first part of this year&lt;/a&gt;. The result is exactly what follows, a streamlined and flattered image of what could clearly be something a lot better. And I knew that, but I took the easy route to see what would come out on the other end.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/bb90119421e324d6890399653c2e1b39/tumblr_inline_mi61s1e9nM1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The result isn&amp;#8217;t dis-satisfying at all, isn&amp;#8217;t it? It just looks too &amp;#8220;coloured&amp;#8221;. There&amp;#8217;s nothing particularly wrong with it: it has its own look, and it steers your eyes towards something you&amp;#8217;ve already seen, only highlighting very different colours this time.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I took a break, and thought about it some more. &amp;#8220;I could do something really different with this picture!&amp;#8221; I thought, and doing the exact same thing &lt;a href="http://dinesharjani.com/post/40942589165/2013"&gt;I&amp;#8217;d been doing with already a bunch of pictures before&lt;/a&gt; wasn&amp;#8217;t cutting it. Then I thought: &amp;#8220;what&amp;#8217;s the only thing wrong with this being &amp;#8216;a perfect snapshot&amp;#8217;?&amp;#8221; The time of day: it&amp;#8217;s bright afternoon, with a horrifying Sun hitting the pavement, instead of a creamy sunset. So sunset it was.&lt;/p&gt;
&lt;p&gt;It took a while; I&amp;#8217;m not going to lie. I researched (Googled) and looked out for help (YouTubed) until I found the method for turning day into night I liked the most: a &amp;#8220;photography filter&amp;#8221; on Photoshop (I&amp;#8217;m on CS5.5), and I worked my way out from there. Colours weren&amp;#8217;t always working for me, but I did my best to try and get the best look. The Sun was still giving the whole thing its glaring light, but it sort of reminded me of the last scene of Mamma Mia!, whom my Dad was quick to point out was shot on broad daylight using camera filters. The end result is here for you now.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/f95cd69da6a840086d7089395a3a87ad/tumblr_inline_mi621biJpZ1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The weakest parts of the image have got to be the pavement, with the harsh sunlight vying for attention, but it did turn out much better than I expected, and part of what I want to do with my photography is not only push for perfection, but to try different things, too. And since the image looked so keen for it, I also made my own &amp;#8220;making-of&amp;#8221; shot, comparing original and final side by side.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/252980b224d3855ded375cfb6b613a2c/tumblr_inline_mi624vbU7u1qz4rgp.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Looks even prettier this way, doesn&amp;#8217;t it? But it sort of helps you visualize what I did and didn&amp;#8217;t do to try to give the image as &amp;#8220;&lt;/span&gt;&lt;span&gt;sunsetty&lt;/span&gt;&lt;span&gt;-look&amp;#8221; as I could.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Since this (&lt;a href="http://500px.com/photo/24131629"&gt;I posted it on my 500px on Jan 25&lt;/a&gt;) I&amp;#8217;ve been hitting myself more traditionally with HDR, but in a different kind of way as &lt;a href="https://twitter.com/dinesharjani/status/301409722060386304"&gt;you&amp;#8217;ve seen lately&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;More soon, I promise!&lt;/p&gt;</description><link>http://dinesharjani.com/post/43006631262</link><guid>http://dinesharjani.com/post/43006631262</guid><pubDate>Wed, 13 Feb 2013 11:17:00 -0500</pubDate><category>photography</category><category>sanfrancisco</category><category>transamericapyramid</category><category>pyramid</category><category>sunset</category></item><item><title>Google’s Notebook
I know it’s quite easy to say...</title><description>&lt;iframe width="400" height="300" src="http://www.youtube.com/embed/d2dhMKSKGBg?wmode=transparent&amp;autohide=1&amp;egm=0&amp;hd=1&amp;iv_load_policy=3&amp;modestbranding=1&amp;rel=0&amp;showinfo=0&amp;showsearch=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Google’s Notebook&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I know it’s quite easy to say “I’ve been thinking about this” when something not even remotely related to what you want to talk about spurs out of the vast ocean that is the web, but it’s true this time. And besides, I don’t need an excuse to talk about whatever I want to with you guys.&lt;/p&gt;
&lt;p&gt;After watching countless Google I/O sessions, reading a ton of stuff on Google, tweeting with people I’ve never met IRL about the company and so on, one thing has always been clear to me: Google is fond of MacBooks. Now, from what I’ve heard, inside the company you’re free to work on either Mac or Windows, but one thing is very clear to me: Google adores Unix, and its favorite kind of Unix, is OS X.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Now, keeping this in mind, and remembering Google has been working on its own pieces of handheld technology &lt;a href="http://youtu.be/e2WtBwAL0SE"&gt;since 2009 when they started building the Nexus One together with HTC&lt;/a&gt;, the question of whether Google would really love to build a notebook designed by and for its own engineers MUST arise. After all; Apple engineers have MacBooks, Windows engineers have &lt;a href="http://youtu.be/1xZyF7l5_8w"&gt;Microsoft’s R&amp;D Department building God knows what&lt;/a&gt;, and every other big tech company can basically use whatever they want. Facebook, I believe, with its hacker culture, must care little about which one you use, as long as you get things done. Start adding the prevalence of Nexus hardware being available (including the &lt;a href="http://dinesharjani.com/post/29203527102/an-ode-to-the-nexus-q"&gt;short-lived Nexus Q&lt;/a&gt;), and the thought of Google engineers making a notebook computer tuned for themselves catches some weight. But we’ve got a few issues to face first here.&lt;/p&gt;
&lt;p&gt;As I mentioned, Google engineers seem to love MacBooks, and although Google’s products have lately demonstrated a tendency to not fall short of their goals, building a laptop with a touch &amp; feel sensation you’re comfortable is only half of the work done. Slapping chips into the hardware isn’t a problem either; Intel would be happy to help you out in any way they can, out of fear of being blown out into history due to ARM’s increasing marketshare in the mobile computing space, and if you went the ARM route, of course, there’s &lt;a href="http://www.anandtech.com/show/6425/google-nexus-4-and-nexus-10-review"&gt;plenty of powerful hardware there at your disposal&lt;/a&gt;. No; the problem is software.&lt;/p&gt;
&lt;p&gt;Because obviously OS X cannot (and &lt;em&gt;will not&lt;/em&gt;) be licensed to any other manufacturer, at least in the following months that’s not a trend anybody of us closely watching the Valley can bear the sight of. No. Is the answer Chrome OS, then? ARM hardware could run it, although I doubt Google engineers building their own hardcore laptop would want an ARM SoC instead of a powerful Intel/Nvidia-AMD combination. Or maybe, what’s important is not the performance, but what they want to use that laptop for. So. What does a top-notch Google engineer need?&lt;/p&gt;
&lt;p&gt;Bare minimum? A working Unix console. If you have a Unix console, you can use Unix’s most powerful tools, write code on Vim, and commit using git. Whether you’d be able to actually debug what you’re coding is an entirely different matter, but that’s exactly what brings us to the point regarding this machine’s OS: if it’s Chrome OS, your coding is limited to the web, or maybe Chrome OS itself. The only viable (remaining) alternatives are either Linux or Windows, since OS X is out of bounds.&lt;/p&gt;
&lt;p&gt;If this is indeed a Chromebook, I doubt it’s “made by and for” engineers, since if I were a Googler, I’d find it quite lacking as my main machine, unless I could get at least Windows 8 on it. About the touchscreen, it doesn’t really seem relevant to me, and if it really is 2560x1700, well, I bet it’s mainly a marketing scheme; nothing really to talk home about. I’ve said in the past &lt;a href="http://dinesharjani.com/post/28781373846/as-good-as-its-seams"&gt;I want a 1920x1080 “point” screen at 2x resolution, not 1440x900&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For now, these are the thoughts I’ve got on this latest assault from the web. Whether it proves to be real or not, is an entirely different subject. A “Pixel” as I/O 2013 gift? Those are going to be a few lucky attendants, really…&lt;/p&gt;</description><link>http://dinesharjani.com/post/42533439182</link><guid>http://dinesharjani.com/post/42533439182</guid><pubDate>Thu, 07 Feb 2013 17:55:00 -0500</pubDate><category>google</category><category>tech</category><category>notebook</category><category>laptop</category></item><item><title>"An unforeseen consequence of ditching my smartphone for my brick-dumb Huawei is that I don’t have a..."</title><description>“An unforeseen consequence of ditching my smartphone for my brick-dumb Huawei is that I don’t have a camera on my phone. And so try to imagine this: I hung out with a girl for multiple months. Saw her multiple times a week. She even met some of my friends, I even met a few of her friends. And I don’t have a single photo of her.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;p&gt;So, I’ve been quite busy for the last 5 days with pictures. First it was with my own pictures, and then it was with a set of 300 pictures of my friends. It doesn’t look like it, but it is a lot of work for me; a lot of work that I incidentally love to do.&lt;/p&gt;
&lt;p&gt;Whilst waiting for another assault of Facebook notifications, I started spinning my usual set of 10-35 Chrome tabs (yup) and one of then happened to be &lt;a href="http://www.theverge.com/2013/2/6/3955678/offline-love-loss-dating-without-facebook"&gt;this article&lt;/a&gt; by “&lt;a href="http://www.theverge.com/2012/4/30/2988798/paul-miller-year-without-internet"&gt;the man who’s (&lt;em&gt;nearly&lt;/em&gt;) spent a full year off the Internet”&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Quite a story. Quite a paragraph; that must be the single most emotional piece of writing I’ve read in quite a while.&lt;/p&gt;&lt;/em&gt;</description><link>http://dinesharjani.com/post/42443737986</link><guid>http://dinesharjani.com/post/42443737986</guid><pubDate>Wed, 06 Feb 2013 14:42:35 -0500</pubDate><category>social</category><category>tech</category></item><item><title>Formula One rolls out of the door
You wouldn’t normally...</title><description>&lt;iframe width="400" height="225" src="http://www.youtube.com/embed/-t6cxIeCIjE?wmode=transparent&amp;autohide=1&amp;egm=0&amp;hd=1&amp;iv_load_policy=3&amp;modestbranding=1&amp;rel=0&amp;showinfo=0&amp;showsearch=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;Formula One rolls out of the door&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You wouldn’t normally expect me to be talking about Formula One, and much less, you’d expect to see me posting a video here about Red Bull Racing, the team that won both World Championships against Ferrari and Fernando Alonso just a few months ago. Yet, even though &lt;a href="http://youtu.be/v0ZQaa1ENoM"&gt;the Scuderia posted a video on Friday of their beautiful new car, the F138&lt;/a&gt;, I have to give it to the boys and girls of Milton Keynes, who definitely made a much better video.&lt;/p&gt;
&lt;p&gt;For someone who lives to work in the world of motorsports, I know these videos are nothing else than “business”; in other words, the kind of things they have to do to actually pay the bills of what they really love to do: build cars that go really really fast, cars that abide by the rules (or are not caught if they don’t), and most importantly, cars which are faster and cleverer than the competition’s. That’s what really drives this kind of people.&lt;/p&gt;
&lt;p&gt;Nevertheless, that doesn’t mean we just can’t sit and enjoy the show, right? Moreover, if Ferrari shot the pictures of the new F138 with a full suite of photographers armed with Canons and Nikons, Red Bull decided it wasn’t enough to just beat everyone else in the video department, but also in the cameras used for the promotion shots: medium-format Phase One cameras, people!! &lt;/p&gt;
&lt;p&gt;Oh, I’m never going to have enough of this sport. When are you guys going to invite me to do some really good work for you? I bet I can make that new two-tone Ferrari colours shine better than anyone else ;)&lt;/p&gt;</description><link>http://dinesharjani.com/post/42205140619</link><guid>http://dinesharjani.com/post/42205140619</guid><pubDate>Sun, 03 Feb 2013 13:53:47 -0500</pubDate><category>F1</category><category>Formula1</category><category>Motorsports</category><category>photography</category></item><item><title>Against The Informer(s)</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/788333bd9fdf19010bac47d2381a3bdf/tumblr_inline_mhgc5fMHwp1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Apparently, I&amp;#8217;m not the only one who deeply misses &lt;/span&gt;&lt;a href="http://www.tv.com/shows/gossip-girl/"&gt;Manhattan&amp;#8217;s most flattering show in recent years&lt;/a&gt;&lt;span&gt;. I thought I had it bad, chasing every week the ups and downs of a set of cool kids fresh out of high school, fresh out of college (wait! did they ever finish? I can&amp;#8217;t remember a graduation episode&amp;#8230;) who clashed with each other barely understanding what was the right way to cope with their feelings, but at the same time, I absolutely loved the show. It wasn&amp;#8217;t entirely reasonable, the show barely made sense in the real world, but it made sense to me, because it got rid of anything else that wasn&amp;#8217;t just &amp;#8220;feelings&amp;#8221; and it allowed its characters a &amp;#8220;do what you want and get away with it&amp;#8221; approach, no strings attached; it was all pure desire, emotion, and self-satisfaction. Something we barely get in a world where we&amp;#8217;re more busy of being kind and taking care of others instead of pursuing what we really want and asking for it if it&amp;#8217;s in someone else&amp;#8217;s hands to give it to us: and yes, you&amp;#8217;re allowed to take those words and give them the meaning you need them to have, that&amp;#8217;s why I wrote for you.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Right, let&amp;#8217;s cut to the chase.&lt;/p&gt;
&lt;p&gt;About a week ago, I noticed my group of close friends started &amp;#8220;liking&amp;#8221; a page in Facebook, it was called &amp;#8220;&lt;a href="https://www.facebook.com/pages/El-Informer-de-la-ULL/181742308616566?"&gt;El Informer de la ULL&lt;/a&gt;&amp;#8221;. Its cover picture and its name, translated to Spanish &amp;#8220;The Universidad de La Laguna&amp;#8217;s Informant&amp;#8221; made me believe at first it was some kind of politics movement; an insider who was within the main campus of the University and who was happy to spill the beans on what exactly was going on with the money the University has been raking in, especially this year when they handsomely increased our tuition fees. Except it wasn&amp;#8217;t that.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Instead, it was the mere apparition in my environment of &lt;a href="http://www.antena3.com/noticias/tecnologia/nace-fenomeno-informer-facebook-cotilleo-universidades-catalanas_2013012300173.html"&gt;a movement started at the Universidad Autónoma de Barcelona&lt;/a&gt; by which a group of people, or perhaps only one, decided they missed &lt;em&gt;Gossip Girl&lt;/em&gt; too much, and turned it into a reality. But of course, this being 2013 (yes, it&amp;#8217;s that fresh), opening up a blog and setting it up was too much work, so instead, a Facebook Page was the host of this new gossip hub. The way it works is the one you&amp;#8217;d imagine: people send private messages to the [Facebook] page, which gathers all the messages, and posts them anonymously, more or less often depending on the amount of gossip gathered in the last few hours. The movement caught fire, and it wasn&amp;#8217;t enough to have one per University, so there&amp;#8217;s one per School; in fact, the image you see above is of the public Facebook Page of my own &lt;a href="https://www.facebook.com/pages/El-Informer-de-la-ETSII-ULL/485169091525172?"&gt;Computer Science School&amp;#8217;s Gossip Facebook Page&lt;/a&gt;. Or &amp;#8220;Informer&amp;#8221; if you will.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not going to lie. My first impression was sort of mixed. At first, my inner devil (yup; still not done with &lt;a href="http://www.amazon.com/Fifty-Shades-Trilogy-Darker-3-/dp/034580404X/"&gt;Fifty Shades Trilogy&lt;/a&gt;, and it shows) crawled out of my heart and began thinking about the kind of pranks you could play with this; after all, you could get away saying anything you wanted about anyone you wanted (hey! I just thought about making a joke to tease a few girl+friends [watch the &amp;#8216;+&amp;#8217;!!!], tell me you wouldn&amp;#8217;t have thought something similar!), and then play &amp;#8220;oh hey! I read this the other night on Informer&amp;#8230; guess whom I think they&amp;#8217;re referring to?&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Then, it dawned on me: &amp;#8220;I wish this page didn&amp;#8217;t exist&amp;#8221;. I wish none of the Informer pages existed, to be more precise.&lt;/p&gt;
&lt;p&gt;Thing is, &amp;#8220;&lt;em&gt;with great power, comes great responsibility&lt;/em&gt;&amp;#8221;, and this is so wrong on so many moral levels. Yes, it could be used to play pranks on the people you know &amp;amp; love in a new and exciting playground (for God&amp;#8217;s sake, lock your computer&amp;#8217;s screen EVERY TIME you leave it unattended, even if it&amp;#8217;s just for a matter of seconds!!!), but at the same time, it wouldn&amp;#8217;t be too comfortable for someone to get the impression he/she&amp;#8217;s being &amp;#8220;admired&amp;#8221; (that&amp;#8217;s the term I&amp;#8217;ve been reading lately as a stand-in for ogling) now, would it? I mean, wouldn&amp;#8217;t it make you uncomfortable to feel you have some kind of stalker constantly watching your moves and trying to get as much information about you as possible? (I know it can be considered &amp;#8220;sweet&amp;#8221; in special cases, but that&amp;#8217;s not my point here.) Suddenly &lt;span&gt;(and for example! don&amp;#8217;t take me word for word!!)&lt;/span&gt;&lt;span&gt;, all of the things &amp;#8220;hungry&amp;#8221; (for lack of a better term) boys think upon seeing a pretty girl now have a very convenient megaphone to &amp;#8220;inform&amp;#8221; the whole campus; and this particular use of the &amp;#8220;service&amp;#8221; won&amp;#8217;t just be confined to the classic gang of boys who look very tough when they&amp;#8217;re together but can&amp;#8217;t face an honest stare from a girl who has a little sense of self-respect for herself on a one-to-one. And it gets worse. Taken outside the &amp;#8220;group of people who know each other&amp;#8221;, or even the people who look at each other every day at School (you know, the classic &amp;#8220;I know who you are but we&amp;#8217;ve never really talked&amp;#8221; look), but are mature enough not to take it any further, things can get amazingly out of control. Imagine this: you&amp;#8217;re fresh out of high school and your hormones just don&amp;#8217;t have any conscious deterrant against speaking out loud about a personal fallout with another freshman. Where do you think you&amp;#8217;ll go to voice your, er, &amp;#8220;concerns&amp;#8221; regarding that other student? To your gang, or to the &amp;#8220;Informer&amp;#8221;? Worse still: at a high-school age, where it appears we humans are not designed to have any sense of empathy towards one another (not only boys on boys, girls can be pretty mean on other girls too), how do you think this kind of firepower will be used, and to what effects?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Consequently this opens two entirely new chapters in the book of how social networks are being misused, the first of which, is yet another dimension to the concept of bullying. You might&amp;#8217;ve laughed at the whole concept of &amp;#8220;Informer&amp;#8221; pages being prominent in high-schools, but this is the kind of thing that just speaks to wannabe college students who want to get ahead of themselves and live up to the standards of the older kids, meaning kids who&amp;#8217;re almost out of high school will use this kind of tool to their advantage, and leave behind a new kind of traumatised children. Because let&amp;#8217;s be honest here; I&amp;#8217;ve always been in favor of technology as a tool to connect us with our people, not to pin the dirt we may have on each other on a public board, which is basically what &amp;#8220;Informers&amp;#8221; are. And regarding high-school and early college, what do you think kids are most interested in? Sex, and most importantly, who has it and with whom. And if such news is already the kind of gossip you find out even if you try very hard to remain oblivious to, imagine if suddenly all of those bits of your past become letters written in an ink that spreads amongst hundreds of servers across the globe which will be there standing the test of time. No, this is not what &lt;a href="http://dinesharjani.com/post/18929714912/digital-cutouts"&gt;I had in mind when I thought about how these &amp;#8220;digital cutouts&amp;#8221; could actually be good for our legacy&lt;/a&gt;. Not at all.&lt;/p&gt;
&lt;p&gt;The second chapter is of course, the whole idea of &amp;#8220;how much censoring are the so-called Informer(s) entitled to do?&amp;#8221;. After all, if we were really against the idea of a certain individual (or set of) being responsible of all our secrets, we would choose another one and support that Informer by &amp;#8220;liking&amp;#8221; his/her page and sending him/her our messages to transmit, wouldn&amp;#8217;t we? But of course, that&amp;#8217;s half the point: we don&amp;#8217;t really know who that Informer is, and if someone does, it could prove to be a very effective weapon. Who&amp;#8217;s to say these Informers are not good-looking scams set to just gain power on campus and get sent all the dirt around town? No, people can&amp;#8217;t be as textbook-characters as a teen drama portrays, right? Of course not! Because if there&amp;#8217;s something I&amp;#8217;ve learnt in twenty-five and-a-half years of existence, is that real life stories tear those of fiction when it comes to heartlessness.&lt;/p&gt;

&lt;p&gt;Listen. I know this seems like a pretty big and grumpy rant, but I really, really believe, &lt;em&gt;Gossip Girl&lt;/em&gt; shouldn&amp;#8217;t exist as such in the real world. It worked on a TV show because it was only about a group of six kids and the people entering and exiting their lives; if it wouldn&amp;#8217;t work as a show to have a gossip blog about a whole town, do you really think it&amp;#8217;ll work with real people living in real towns and real cities? You think this is somehow going to improve your life in ANY level? No, it&amp;#8217;s not. Don&amp;#8217;t kid yourself. And if you don&amp;#8217;t believe me when I imply people are, from what I&amp;#8217;ve seen, &amp;#8220;behaving&amp;#8221; up to a certain point until now, I&amp;#8217;ll use a real life example I got off &lt;a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X/"&gt;one of the books I&amp;#8217;m busy with&lt;/a&gt;: suppose you leave a five year-old car parked in a neighbourhood known for its disturbia, what do you think&amp;#8217;ll happen after a week? Nope, not at all; the car will be untouched. But take a small rock and use it to break the car&amp;#8217;s window; people will get the message &amp;#8220;nobody cares about the car&amp;#8221;, and they&amp;#8217;ll start hammering it down, little by little. And by the end of the day you broke through the car&amp;#8217;s window, its ashes will be the only thing left to remember that it really stood there.&lt;/p&gt;
&lt;p&gt;Please, listen to me. Let Informers die, do not hand them over any more oxygen, and let&amp;#8217;s not add these online local gossip boards to the ever-increasing list of disrespectful manners which already clutter our legacy. For our kids. Four our grandkids. For our future generations, please forget these sites exist. Live past them.&lt;/p&gt;</description><link>http://dinesharjani.com/post/42113148230</link><guid>http://dinesharjani.com/post/42113148230</guid><pubDate>Sat, 02 Feb 2013 12:53:05 -0500</pubDate><category>Tech</category><category>social</category><category>people</category><category>personal</category><category>facebook</category><category>gossip</category><category>gossipgirl</category></item><item><title>iPad 5
The thing I like the most about tumblr, is the wicked...</title><description>&lt;img src="http://25.media.tumblr.com/1c62d18d4e0c36ed7a97a970f60ea45b/tumblr_mheik2w7jt1rnh17xo1_500.png"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;iPad 5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The thing I like the most about tumblr, is the wicked ways in which it allows you to present your own posts. This one for example, allows me to start by calling you out to look at the picture first, then read. If I do it otherwise, you’ll struggle to read first the post’s title, because before reading me, you instinctively want to check what this post’s about, and check if it’s worthy of your time. But here, I have the power about such simple things, haha. And I love it!&lt;/p&gt;
&lt;p&gt;So, iPad 5. To begin with, I don’t necessarily give credit to these kind of “&lt;a href="http://www.theverge.com/2013/1/28/3926532/5th-generation-ipad-part-potentially-revealed-in-leaked-image"&gt;rumor posts&lt;/a&gt;” that begin the silly season every year talking first about an incoming iPad, and later in the summer about an incoming new iPhone. And its mini counterpart (talking about the second.)&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Today though, I found this picture rather interesting: it made total sense. Dropping the “new iPad” in Spring of 2012 made total sense; updating it just a mere 6 months later with twice the power (in both fronts: CPU and GPU) didn’t; it made Apple look as if they were the ultimate performance junkie, when Steve proudly believed that PC makers trying to shoe their way into “mobile devices” were talking about speeds and feeds, which was the wrong way to get about these kinds of computers. (Yes, they are computers.) By the way, nothing to do with the fact &lt;a href="http://pandodaily.com/2013/01/18/the-apple-dilemma-marketshare-or-margins/"&gt;Apple has been stumbling quite badly with Wall Street investors in recent months&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Continuing my derailment. Up until the iPhone 4, Apple released phones at WWDC. 2011 changed that with the 4S, but I suspected we’d see a new iPad come Spring 2012, and so &lt;a href="http://dinesharjani.com/post/19059329336/new-ipad"&gt;we did&lt;/a&gt;. A new iPad, built on the same body as its predecessor and the venerable iPad 2, released months later didn’t make any sense at first, but then &lt;a href="http://www.anandtech.com/show/6472/ipad-4-late-2012-review/5"&gt;it did&lt;/a&gt;. So rather than a big mistake, it was actually a correction: the iPad 3 was the mistake being too early (too underpowered) at the party, but then Apple wanted to showcase their mobile business came before their Mac business, and so, the “Retina” moniker had to fall upon their full line of iDevices before it did to their premium line of Mac portables, because make no mistake, the classic MacBook Pros are going to die; I expect the “Air” to become just “MacBook” and the “Retina” models to drop the “Retina”. So sad there won’t be a 17” Retina MBP.&lt;/p&gt;
&lt;p&gt;The consequences? Despite the rumor mill, I do not expect either a new iPhone nor a new iPad until the Autumn, where both lines were updated last year. Rumours pointed at a 128GB iPad; I never believed it’d happen so soon, but there you go: &lt;a href="http://www.theverge.com/2013/1/29/3928066/apple-announces-128gb-ipad-with-retina-display"&gt;the 4th-gen iPad now comes in a 128 GB variant, and as of today&lt;/a&gt;, in fact. As for the new iPhone… could it switch gears and be announced at WWDC? I don’t discard it, though I don’t necessarily expect it. If it does, we’ll see the appropriate smoke, it’s like that these days. What I do expect is a little something called OS X 10.9, which, a year ago, was announced, to my shock, &lt;a href="http://dinesharjani.com/post/17739931947/kaboom-apple-announces-os-x-10-8-mountain-lion"&gt;somewhere around this timeframe&lt;/a&gt;. So an announcement like that could hit us any day now, with 10.9’s release date &amp; price being announced at WWDC, together with iOS 7. &lt;br/&gt;&lt;br/&gt;Boy I hope iOS 7 overhauls the damn Operating System for once and for all; it’s full of UI-convention rot dating back to the original “iPhone OS” release of the original iPhone sold in June 2007.&lt;/p&gt;
&lt;p&gt;So what’s in the cards for this new iPad? It finally marries together the design of both the iPhone, the iPad mini and the iPad itself. And by the looks of the picture, it seems its designed fell into our hands late last year, in the form of the cool new iPod Touch. For me, it means I finally have a good reason to shell out my money for the next iPad. Not that the Retina display wasn’t enough for me, given the ton of content I read with it and the importance I give to pixel density looking towards my eyes’ health, but it just didn’t feel right at the time. Then Apple came and threw the 3 out of its stores and supplanted it with an equally looking device although much stronger in every department, given its speed improvement permeates every experience with the device. Was it time then? No. Tempting, but no. It still keeps the 2nd-iteration design, and I knew a new design would come after the 3 (I didn’t entirely miss my mark; who expected two flagship iPads in a 6 month timespan!?), and this one does look the part of my iPad 2’s successor, the one I had to wait for outside of San Francisco’s Apple store a good 5 hours to get (I’ll keep a picture for another day. Promise!).&lt;br/&gt;&lt;br/&gt;But there’s one thing I do not buy: the iPad Mini “as”, the better product. It’s not.&lt;/p&gt;
&lt;p&gt;Here’s why: it’s the little brother. &lt;/p&gt;
&lt;p&gt;From the moment I saw it through the livestreamed keynote I knew it would hook anyone who would make the mistake of laying their eyes upon it and holding one with their own hands, but I still kept repeating people the very same thing: if I had one, I’d know there’s a bigger one out there, and that wouldn’t satisfy me at all. Why? Because as it stands, the 9.7” iPad is just perfect for me. The only thing it doesn’t do well? Films, due to its 4:3 aspect ratio, but I’d rather have a 4:3 9.7” iPad than a 10.1” 16:9 (I flipped them to emphasize my point) Nexus 10, and I love the dual ARM Cortex A15 nature of the Samsung-built Google Nexus tablet, but widescreen isn’t for me in the tablet department. I can take it in a Nexus 7, but again, 7 inches is too small for me. The iPad 2 isn’t too heavy for me as some claim, it doesn’t tear its way into my flesh as some comments point out nor is it too big for me: I can carry it quite easily in my backpack, and I bought a case I can wear over my neck if I just want to walk with it as &lt;a href="http://dinesharjani.com/post/20597161988/tagging-you-along"&gt;I did in Hong Kong&lt;/a&gt;. So what on Earth is the problem with it?&lt;/p&gt;
&lt;p&gt;I use it to read, I appreciate its size, and it even gets small in some circumstances, but it’s good enough for most situations, and it surprisingly saves me from taking my 5kg 17” MBP if I want to do some light-study sessions where all I need are PowerPoint presentations (no more printing tons &amp; tons of PDFs!!!!) and it keeps me company after hour of reading in my couch. It’s just perfect!!!&lt;/p&gt;
&lt;p&gt;Now, I understand a smaller size has its advantages, but given what I do with it, for me, the big iPad is the winner. And the fact that the Mini is just a resized iPad 2 with an iPhone 5-esque body at the moment doesn’t make it better for me. It is a tablet I’d recommend though, make no mistake: I only recommend four tablets on the market, the Nexus’ and the iPads. The rest are plain rubbish from what I’ve seen, and I’m glad Google took matters on its own hands when it came to the horrible tablet experience marring the Android landscape.&lt;/p&gt;
&lt;p&gt;So. The 5th generation iPad. Let’s wait and see how it develops throughout the year, and hopefully, I might be able to claim one of those as mine. Unlike some other things I said I &lt;a href="http://dinesharjani.com/post/25175308368/looks-good-to-me"&gt;might claim&lt;/a&gt;, but we’ll get back to that later.&lt;/p&gt;

&lt;p&gt;Wait. I do that too much, don’t I? &lt;/p&gt;
&lt;p&gt;Oh, my.&lt;/p&gt;</description><link>http://dinesharjani.com/post/41801117573</link><guid>http://dinesharjani.com/post/41801117573</guid><pubDate>Tue, 29 Jan 2013 14:44:00 -0500</pubDate><category>Tech</category><category>Apple</category><category>iPad</category><category>iPadMini</category></item></channel></rss>
