Archive for March, 2011

11 MarGIT will organize your development process

This long weekend I seriously decided to dive to Git. Everybody heard about a distributed revision control system, but most were afraid to try this Linus Torvalds child. I was one of that guy, despite the fact I used more that 10 GitHub projects before and watching for many projects.

Git

  • Yes, it’s hard to start and not easy to use.
  • It’s not like SVN, but really about another way to think.
  • Sometime processes seem too complicated, but after a few days everything looks reasonable.
  • There were two reasons I kept going to this for a while.

Open source 
More and more project I use from Github. Sometimes I improve them, but don’t “commit” back to the main repository. So morally I wasn’t paying tribute to developers and the community (beautiful community graph). As well in practice I have problems with updating modified sources with new one from GitHub. No chance for merging. It’s just unnatural.

Own source
The second problem I felt for past months is about organizing own classes. Since we started to work together as a team It’s become really actual to build a common repository with reused classes.

SVN
I’ve been keeping all my sources under SVN during last two years. It’s included to my hosting plan. Easy to commit if no hard merging. Good Mac client – Cornerstone.
SVN to Survive

But now it’s a discomfort in collaboration inside the team and over the #iphonedev community. For example, two weeks ago we created 3 (THREE!) version of the same application to verify ideas. It was about MGSplitViewController from GitHub. Moreover after we found a solution it’d be better to commit changes to the GitHub, but didn’t do that. Yes, it’s our own fault, but tools have to encourage to go right way. Now we have two different own splitControllers in two projects. It’s representative, isn’t it?

After that I read an article in russian where guys described how they faced very similar problems and tried to use SVN further.
Use Git
  • I started to read about GIT from several articles. It helped me (ru) to understand what problems people have and how they solve them. Read a few in russian.
  • Then I started to try. After many hours of experiments I felt a lack of theoretical knowledge, so I found a good book – Pro Git. It’s translated to many languages, e.g. russian.
The plan

  1. Move common Categories and low level classes to common repository. E.g. AvatarManager, Settings, LocatorSingleton, etc.
  2. Determine and move base classes to the repository. I always had a few, but they migrate from project to project and have 10 different versions. This wrong way of source organizing makes more and more discomfort. Examples: BaseViewController with messages, delegates and activity indicator; ListViewController, SearchViewController, etc.
  3. Then move more powerful Controllers that are very similar and used more than twice. E.g. SplashController, SynchTableViewController and NearOnMapsController. Such controllers should be refactored and tested. That’s why it’s actual for active project only. And it’s better to extract them during a real project or refact two old projects simultaneously.

The challenge is to support own lib with numerous branches, often pushes (commits to the origin/master) back and keeping other branches fresh. The terminal is only way to manage this process because it’s easy to be confused by a list of 5–10 branches of one lib for different projects, if you see them all together in a GUI client. Maybe we’ll think about automatic update mechanism.

Git practice
The first an easy but completed thing I did was a NSTimeZone-Localization update. I read through my RSS feeds and found a Cocoanetics’ post about open source project for NSTimeZone translating. Sure I could translate it to russian. So i did that and push my update to my fork, then made a Pull Request. A small but useful lesson.
What’s next?
Now I am refactoring active Alterplay projects starting from the freshest one. I am convinced that it became easier to integrate GitHub projects to existing SVN project.
Next steps are:
  • learn to work in Git team and product style and test knowledge on next customer project
  • determine more common classes and organize Alterpaly library (APLib) as a GitHub private project
  • to convert inner SVN projects to GitHub and implement Git’s submodules
  • open the Alterplay Lib to the iPhone development community part by part
I’m glad to see how sources and then dev process become more organized with right tools.

07 MarHuman Interface in practice on Debty app

We’ve released new product recently. It’s called Debty. It helps to manage debts of your friends. There is a banner at the right top. If you want a promocode please request it on the twitter.

The goal was to develop something easy to use with limited features. Developing it we’ve got some useful ideas I want to share.

Design

The very custom design was also required. After a few hours of research Jeans style was chosen. I hope you’ll like it.

Beside it’s really hard to develop and support custom designs, now I see it’s too custom. App design should be more simple and less like “cartoon”. Too much details, textures and volumes are pleasure to look first 3 times, but then they detract from the main thing – functional parts.

No matter how much your design is custom or unique or extravagant, you have to abide by the law of HIG (Human Interface Guidelines). It means your controls should be right sized and placed, e.g. buttons in the UINavigationBar, and you may still use the same navigation principals with UINavigationController or UITabBar. etc.

OK-message sucks

As less OK-messages you have, better your application is. Means you shouldn’t notify user “Your tweet is posted. Press ok to continue.” – use sound notification instead or “Profile is saved” – show some small animation in saved block instead.

So just take every OK-message from your app and ask “is it really required?” and “How could I notify user without OK-message?”. You’ll see how easily you invent some new approaches. Nobody says it’s easier, but worth that.

I think that’s a different between User Interface and Human Interface.

So please look this next short. There are some tiny animations which we are proud of.

  • “Enter an amount” and “Select a debtor” OK-messages are replaced by soft vibration of inputs
  • View and Edit views are combined in one view which transforms with animation to one state to another. Yes it’s like Contacts.app does.
  • Every date has human representation like “Today”, “Tomorrow”, “3 months delay”, “refund in 8 days”. it’s changed on the way while editing.

The best UI is absence of UI. It’s so much natural to not require time for adaptation.

04 MarSmart logging for unsatisfied with NSLog

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial; min-height: 16.0px}

Logging is very useful and powerful tool. All iOS programmers knows about such great method as NSLog(NSString *format);

But there is one problem on active usage of that method – usually you don’t need to logging something in Release version of a product, because logging need resources.
Let’s take a look on two solutions to avoid.
But to start a little prerequisites.
1. Open your project settings (Project -> Edit Project Settings).
2. Go to the ‘Build‘ tab.
3. Make ‘Debug‘ as currently selected configuration.
4. Set ‘DEBUG=1‘ to configure Preprocessor Macros.p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}

First solution
1. Add the following macro into *Prefix.pchfile

#ifdef DEBUG    #define LOG(...) NSLog(__VA_ARGS__)#else    #define LOG(...)#endif

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial; min-height: 16.0px}

This allow us to use LOG() macro from whatever place in the programm instead of NSLog() using and also this disable logging for Release versions.
Simple and convenient. But this method has one drawback. What if the project is large and the information it logged a lot? If so you will get much unnecessary info in your console. But this is not a problem, let’s go to the second solution.
Second solution
The idea is to split all info to a different urgency levels and allow to configure which levels we need to write into log. Let’ go.
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}

1. Add new class into the project and name it ‘Log‘.
2. Add macros for different urgency levels into Log.h
  LOG_LEVEL_MOST_IMPORTANT – for high priority information
  LOG_LEVEL_NORMAL  – for normal priority information
  LOG_LEVEL_COMMON  – other information that doesn’t need much attention (debug info etc.)

#define LOG_LEVEL_MOST_IMPORTANT 1#define LOG_LEVEL_NORMAL 2#define LOG_LEVEL_COMMON 3

 

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}

3. Add method definition for logging
+ (Void) log: (NSString *) message level: (short) level;

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}

Log.hfinal version should looks like:

#define LOG_LEVEL_MOST_IMPORTANT 1#define LOG_LEVEL_NORMAL
2#define LOG_LEVEL_COMMON 3 @interface Log : NSObject {} +
(void)log:(NSString *)message level:(short)level;

@end
4. Add two directives into Log.m 
LOG_LEVEL_NOTHING - show nothing in console
CURRENT_LOG_LEVEL - show information with current detalisation level (is equal one of LOG_LEVEL_xxx macros). This directive must be wrapped by #ifdef DEBUG … #else … #endif to avoid logging in Release versions.
#define LOG_LEVEL_NOTHING 0 #ifdef DEBUG    
#define CURRENT_LOG_LEVEL LOG_LEVEL_ MOST_IMPORTANT#else
#define CURRENT_LOG_LEVEL LOG_LEVEL_NOTHING#endif
5. Implement method for logging

+ (void)log:(NSString *)message level:(short)level { if (CURRENT_LOG_LEVEL >= level)
NSLog(@"%@", message);}

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica; min-height: 17.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}

Pretty simple.. huh?
6. The last step – add import of Log.h into *Prefix.pch that allow us to use our newly created logging method
#import “Log.h”

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}

Now you can use
[Log log:@"test message" level:LOG_LEVEL_COMMON];
to log information with normal urgency level, or
[Log log:@"Warning! Server not response!" log:LOG_LEVEL_MOST_IMPORTANT];
to log most important information, like problems with connection to a server or whatever.

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Arial; min-height: 16.0px}

For tests in different versions you can set CURRENT_LOG_LEVEL = LOG_LEVEL_MOST_IMPORTANT.
This allow to write most important information into the console.
Of course, this solution is not as elegant as using of the LOG() macro, but it is quite flexible.