Friday, December 12, 2008

Story behind Mail2Group

Why did I develop Mail2Group? App Store Link
* Though, not a heavy email user, I often find myself sending emails to more than one and usually with almost same information. As a Consultant, I email out weekly time sheets, reminders, progress updates to my managers and clients. Doing so, I found myself entering the same email address, subject and body texts most of the time. And, as you all know though iPhone is a great piece of work, it still misses some nice key features. One such feature was being able to create a group that you could use for email or SMS. The release of iPhone SDK inspired me to create an app to fulfill my personal need and fill the gap that was missing out in iPhone. Hence, Mail2Group was developed. I spent close to 2 months developing, as the app went through several iterations. I spent most the time thinking about the UI as I wanted the users to be able to use my application without any instructions. Hence, a lot of care was taken to make the app look similar to iPhone's Phonebook UI which all the users are familiar with.

Why create new groups instead of using the one in Phonebook?
* When I started to develop, I wanted to make sure to give the user a lot of flexibility in how they would like to use my application for their needs. One of the most important thing was being able to configure To, CC and BCC labels to contacts, set subjects, and also be able to add email address of contacts that are not part of your phonebook (personally, I didn't want to add my clients information to my phonebook). After some research, I found if I use the Groups framework in iPhone SDK, I will be running into a lot of synchronization issues and it also raised a lot of UI questions like:
  1. What happens when a contact has multiple email address? Should, I add them all to the list or let user choose one.
  2. What happens when a group gets deleted externally through some other app? Should, I still keeps the details or discard it. If i discard, should I inform the user that a group doesn't exist anymore.
  3. And finally, load up time and performance. Since my goal was to provide a nice user experience I was not willing to sacrifice performance.
and many more......

So, I found out that even I use the existing groups in the phone book, I would still have to hold the same anount of information that I would have to hold if I don't use the phonebook's groups.
Hence, I decided to go with the option of creating groups that are only available to Mail2Group application.
But, I am still trying my very best to add the ability to use the phonebook's groups without scarificing any of the features or performance.

How your reviews helped me?
I am very thankful to all the reviewers on the App Store and users who had sent me their feedbacks and helped me add some great features. Few such features that were implemented based on feedback/reviews are:
  • Sort Groups by Name
  • Exclude a Contact without deleting him/her from group
  • Copy an existing group to a new group (i.e., using existing group as template)
Who are my App users?
After developing, I spent quite some time on thinking about pricing and marketing options. I realized that my app is not meant for all the iPhone users out there (Although, I will be extremely happy if everyone uses it). So, I decided my goal is reach the users who will be really benefited by an app like "Mail2group" and serious users don't mind spending couple of bucks for a quality app. After all, we all bought an iPhone in spite of the high cost Why? It has quality in it.
So, after careful consideration, I decided on a dollar amount.

Hope you enjoyed reading my story, feel free to leave any comments as you like. Good or bad. It's always welcomed.

Monday, September 15, 2008

Mail2Group Feedback & Reviews

Post your questions, comments about the Mail2group iPhone application. Any ideas or improvements are greatly welcomed.

Sunday, April 13, 2008

My first iPhone Native application

Almost a month after the SDK release, I finally was able to build a native iPhone application. The application  is a translator application that could be used to translate text from english to eight different languages. Apart from text translation, the app supports dictionary and web page translation. This is still in a WIP. It uses the Google's Translation Data API to perform the translation. I still have some issues with encoding and needs more cosmetic work. I have also planned to add a save feature that will let the users save the translated text and view it later. It will also provide a easy way to email it or SMS (not sure). This application will also provide a URI that will allow other native apps to launch and translate text.

Wednesday, April 2, 2008

iPhone SDK + Interface Builder

I was so excited with the release of iPhone SDK and hoped I would be developing apps in no time like the demo showed by "Steve and his friends" . But not for long, I have almost entered the total frustration mode. Apple did a good job on their release with the first version of SDK with lots of documentation and example. The second version came as a complete disappointment to me. I can't believe they released a Interface Builder with absolutely no documentation or guide except for 10 lines of Release Notes. I am a complete newbie to Cocoa Framework and Objective C, never used IB but I am clearly not a bad developer. I have developed so many different apps for different platforms with different framework.
I really hope Apple releases a new version of their SDK + IB with more documentation/samples/guides.

Meantime, after some serious searching on the web I came across this link

I believe it's a blog of another frustrated developer but he has a nice tutorial on how to use the IB with the SDK.

Thursday, January 24, 2008

I want it and don't want it

"There is something in the air" Probably, most of you out there were going crazy on trying to speculate what possibly could it be. Later, it turned out to be a very special something "Macbook Air". It's so far the thinnest and coolest looking laptop ever. No doubts on it. The moment, I saw it I said to myself "I am buying one" like I did it with the iPhone. But now, I am contemplating.. why? BTW, I love my iPhone and I feel it is the best purchase I have done in the past year (My PS3 takes the second place). So, here are my thoughts as to why I am contemplating?

It is definitely not the price (it's little high I agree), missing optical drive, or less hard drive memory but, Simple usability issues:
  • I read today I can't use the Magsafe adapter from other Macbooks or Macbook Pros. Are you kidding me? It's so common to people to share their power adapters all the time especially when you are at meetings, conferences or even at home. I love the Nokia cellphones for this one reason, one power adapter can work with several Nokia handsets (at least, it used to be this way)
  • Remote Disc: It doesn't let you install Windows (not very important), watch DVDs (important) or import Music MP3's or Audio CD's (very important). So, is this utility any worth to general people?
  • Oh, so why don't I buy the Super drive and not bother with Remote disc. There is a catch. I can't use the Super drive with any other laptops or PCs, not even with a Macbook Pro. Apparently, the regular USB ports can't deliver the power required by the Optical Super drive.
My thoughts mentioned here are not a big hassle. But, they are definitely something that everyone would miss at least once in few months. Apple, if you really intended the Macbook Air to be not the only computer in a household, then make sure you when you market it add a line "Not for a Single Computer household".

And BTW, I am a Apple Fanboy.

Wednesday, January 23, 2008

Unit Testing Stored Procedures

Testing Stored Procedures at times can get very difficult. I am sure there are several frameworks and tools available out there. But, I wanted to use NUnit and came across this excellent article by Alex Kuznetsov and Alex Styler. Their framework lets you compare results sets and even entire database modification changes. And as expected, rolls back after the tests, so the db is maintained in a clean state.

But, I wanted some initial test data to be populated in the database and at times the initial data need to be different for different tests. To solve that issue, I used NDbUnit, which helped me to put my database in a known state and thereby increasing repeatability in my unit tests.

Using NDbUnit and Alex's Database Testing framework, I was able to build stable and consistent unit tests to test the database table, stored procedures.

If someone would, like to see an example, please let me know and I could send it to you.

Tuesday, January 22, 2008

Postable content

I am new to blogging and I found the following link useful which makes the contents postaable. This comes in handy when trying to post code block or xml markup tags.

Include SVN Revision number in the Assembly Info using Nant

Recently, I decided to include the revision number from the SVN repository into the assembly major/minor build information (e.g., 1.0.1234.0, where 1234 is the SVN revision number). The reason I had to do this, our applications gets installed locally at multiple user's computers primarily for testing/demo purposes and over time, it was getting hard to track the problems/bugs resported as it was too hard to figure which version was installed on their machine. And, nant is used as the primary build tool.

First, let's create a target to retrieve the latest SVN revision number.

<target name="RetriveSVNRevisionNumber" description="Retreiving the latest revision number of the working copy">
<echo message="Retrieving Subversion revision number"/>
<exec program="${tortoisesvn.dir}/SubWCRev.exe" >
<arg value="." />
<arg value="revision.include.default" />
<arg value="revision.include" />

The above section retrieves the version number into the local project. For more details, refer this link.

In our case, the contents of revision.include.default file looks like:

<project name="RevisionSpecificProperties">
<property name="revision.value" overwrite="true" value="$WCREV$" />

Ok, now after retrieving the version number, we need to update our global SolutionInfo.cs file that will hold the assembly information.

<target name="UpdateAssemblyInfo" depends="GenerateBuildNumber" description="Updating the Assembly Information by overwriting the SolutionInfo.cs file with a new one." >
<asminfo output="SolutionInfo.cs" language="CSharp">
<import namespace="System.Reflection" />
<import namespace="System.Runtime.InteropServices" />
<attribute type="AssemblyCompanyAttribute" value="Company Name" />
<attribute type="AssemblyVersionAttribute" value="${build.version}" />
<attribute type="AssemblyFileVersionAttribute" value="${build.version}" />

<target name="GenerateBuildNumber">
<script language="C#">
<import name="System.Globalization" />
<import name="System.Threading" />
public static void ScriptMain(Project project) {
Version version = new Version(project.Properties["build.version"]);
int major = version.Major;
int minor = version.Minor;
int build = version.Build;
int revision = version.Revision;

build = Convert.ToInt32(project.Properties["revision.value"]);

version = new Version(major, minor, build, revision);
project.Properties["build.version"] = version.ToString();


<delete file="revision.include" />

The above targets, creates/updates an existing SolutionInfo.cs file which can be linked to all the projects in the solution so, all assemblies gets updated with the latest revision number in their build info.

Visual Studio 2005 Customizing build process

Visual Studio 2005 provides a great set of features to customize the build process. Recently, I had an requirement to customize the build process for an in house web application to conditionally include files and project references. In my case, I had an web application projects and multiple library projects which were being references by the webapp. For one particular installation, I had to exclude one library project (say Project One ) and several aspx pages in the web app that were using Project One. MSDN had a nice article on a new feature called web deployment project which allows to customize the build process. But, I didn't want to add an additional project to existing solution, so I tried to solve my problem in a different way.

1. I created a seperate build configuration named "ExcludeProjectOne". Right click on Solution->Choose Configuration Manager->Select New from Active Configuration.
2. Uncheck the project you don't want to build in that configuration (Here, it is ProjectOne)

Now, when you choose the active configuration as ExcludeProjectOne, the library project "Project One" is excluded from the build process. But, it still didn't solve the problem in my web app project which references the ProjectOne and some aspx files which uses it. So, I manually edited the Web.csproj file to achieve the desired action.

I created a new itemgroup element with a condition attribute and placed all the necessary files and the project reference inside the itemgroup element.

The above changes allowed to me have a build configuration for the web application where I can exclude the library and the related aspx pages being built.