MAZYOD’S
DEVDIARY

Blabbering on, and on, and on…

Lessons from Jenkins

Introduction

Recently, I was privileged with the task of configuring a mac mini server with Jenkins to automate our build process, and distribute new versions OTA using HockeyApp.

The task was anything but smooth. I did not expect Jenkins to have so many bugs!! Well, less Jenkins, and more the plugins that are around it. Anyways, let’s dive right into it.

Hello, Jenkins

Before anything, you probably want to give yourself remote access to the Jenkins server. Configuring jenkins through VNC, SSH, or other indirect manner is not feasible, as you’ll probably spend quite a few hours working on Jenkins.

Fortunately, this is quite simple. First, make sure that your server is secure by setting up some authentication method. This is done in Jenkins preferences. Choose whatever suits you, so long as not anyone with that knows the IP address of the server and port number can access Jenkins. That would be really bad.

A word of caution: While setting up the credentials, make sure you give the anonymous user full privileges, and only remove them once you’ve set everything up. You could end up locking yourself out of the server, otherwise. (which is easy to fix, but better avoid it altogether)

Once that is setup, open the Jenkins config.xml (possibly located in ~/.jenkins) and change the value 127.0.0.1 to 0.0.0.0. I forgot the exact name of the key, but just tells Jenkins to accept incoming connections from all addresses.

YAY! Now you can play around with Jenkins from your iPad.

Hello, Xcode

This is when I realized how really aweful those plugins for Jenkins are. They are suppose to serve as a UI replacement for common commands used by Jenkins users, but they ultimately fail to deliver. I am sorry if the truth hurts, but I did waste a lot of time on them, and that hurt as well.

If you want to see for yourself, download the Xcode plugin for Jenkins, and just try to build your project through it. It’s hard to specify the freakin details, especially if you have a complex project setup. On top of that, it always added an argument that broke my build, and you can’t turn it off..

In any case, I prefer and ultimately used Shenzhen, which is part of the Nomad cli package. My thoughts?

So painless, so simple, so awesome.

# Unlock the keychain
security unlock-keychain -p PASSWORD

# Increment the build number
agvtool next-version -all
# build the IPA
ipa build --scheme TellyApp-On-Commit --configuration Ad-Hoc
# distribute through hockey app
ipa distribute:hockeyapp -m "Jenkins build" --token

The few lines of script above replaces two Jenkins plugins, the Xcode one and the HockeyApp distributor one.

Hello, GitHub

Github uses a concept called “Webhooks” to do a very convenient thing for us. Once a push has been made to master, or a pull request is submitted, we can tell github, through webhooks, to submit a POST request to our server informing it about the change. This rids us of polling the SCM for changes, and even get instant results!

Those webhooks were a nightmare, though. Throughout the guides I read, there was nothing specifying that you should choose the urlencoded content type instead of the application/json, but you have to do that. Another issue is that Github sends a ping notification first, which fails… I tried to make it work, but ultimately found out that it’s not supported by the Jenkins Github plugin. It is destined to fail, I guess :( …

Goodbye, Everyone

That was what it took to get it up and running! The devil is in the detail, and I am sure I am missing bits and pieces here and there… The main take away is: DON’T RELY ON PLUGINS UNLESS YOU ABSOLUTELY MUST.


How to Logout from Hockeyapp

As silly as it may sound, but there doesn’t seem to be a way for the HockeyApp user on Mac to sign out once he signed in…

With just a tiny bit of knowledge about how the Foundation framework offers app the ability to save preferences, I realized I can probably delete the preferences file:

1
2
3
4
$ defaults find hockey
[... huge lump of text, and somewhere in the middle:]
Found 19 keys in domain 'com.hockeyapp.mac': {
[...]

With the domain of the app figured out (maybe I could’ve just checked the app bundle’s info.plist?), it was as simple as:

1
$ defaults delete com.hockeyapp.mac

And now, I have been signed out!


I Am Blogging, Again!

Holy crap… It has been so long since I last blogged, I missed this awesome feeling of typing things into the computer. In any case, onto the blog!

Introduction

I have came into an important realization today, and that is, the programmer’s philosophy. I am not sure if there is such a thing, but if there isn’t, there sure should be one and it should be taught to all programmers..

Time to Get Philosophical

What is programming? Jk, not that philosophical, just a tad bit.

Before a programmer writes code, there must be something that they want to achieve. That goal is (in most cases) well defined, and can be verified. The approach the programmer takes to achieve that goal can be in so many different ways, I dare say infinite.

Recently, I found myself writing contradicting code. This is because my philosophy hasn’t been laid out before hand, and the span of the project exceeds a whole year, which made me change philosophies quite often…

Time to Get Practical

In my example, I’ll talk about this game backend I have been writing…

So, writing backend code is awesome. There is no GUI involved, it is just pure data manipulation.

Initially, I started writing and designing the backend in such a way that the client doesn’t compute the “business logic”. This means, that the backend does the computation for the frontend, and sends the result…

Today, I while I was implementing this new feature, I decided I want the client to compute the result instead, forgetting that the rest of the code depends on the fact that the backend should compute the logic! I did that because I was thinking about moving computation costs to the frontend.

The moment I realized how I had set everything else up to compute the results in the backend, I switched the implementation to follow that philosophy immediately, and that’s when I came with this important realization…

Time to Realize Things

First, my former self is no idiot. He didn’t decide to compute the logic on the backend for no reason! It was because of security concerns, and that was arguably the right choice, I can still see that.

The issue, though, is when I tried to make the frontend compute the result, I kept bumping into hurdles and obstacles that were very annoying. I am suppose to be at a stage of development where the base is all laid out, why the hell is it so hard to add this simple thing!!

Yes, the realization being, I’m doing it wrong! It is a relief that I am in sync with my former self, so I consulted him, and he told me about the computation thingie… The problem begins when you start working with a team or an open source project.

Conclusion

I love how python, lua, and many language specify their philosophies, but I don’t think there are enough of them out there.


What the Snippet

I am really getting used to this video blogging business. It feels like I want to make all future posts videos. So easy, so convenient…

This one is about using Xcode snippets to speed up your development. I present a use case with cocos2d-x, but it can be used with anything really… Even Swift ;).

Here are the snippets. Just drag the code over to the snippets area in Xcode:

1
2
3
4
5
6
7
8
9
class <#class#> : public <#superclass#>
{

public:

    static <#class#> *create(<#args-definition#>);
    virtual bool init(<#args-definition#>);

};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<#class#> *<#class#>::create(<#args-definition#>)
{
    <#class#> *obj = new <#class#>();
    obj->init(<#args#>);
    obj->autorelease();

    return obj;
}

bool <#class#>::init(<#args-definition#>)
{
    if (!<#superclass#>::init(<#superargs#>))
    {
        return false;
    }

    return true;
}

Regex Fun

Today, I went on a regex mission to refactor our code base, and ended up replacing a huge lot of code with macros, which saved us around 450 lines of code throughout the project. Now, we can use those macros to work faster, too!

Here are all the commands I wrote, good luck figuring anything out :p

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
$ search_grep NSNotificationCenter\s+
$ search_grep NSNotificationCenter\\s+
$ search_grep "NSNotificationCenter\\s+"
$
$ search_grep "NSNotificationCenter\\s+"
$ search_grep "NSNotificationCenter\\s+"
$ search_grep "NSNotificationCenter\\s+"
$ search_grep "NSNotificationCenter\\s+"
$
$ search_grep "NSNotificationCenter\\s+"
$ search_grep "NSNotificationCenter\\s+"
$ search_grep "NSNotificationCenter\\s+"
$
$ search_grep "NSNotificationCenter\\s+"
$ search_grep "NSNotificationCenter\\s+"
$ search_grep "NSNotificationCenter\\s+"
$
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]"
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)"
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)\\s+selector"
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)\\s+selector\\((\\w+)\\)"
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)\\s+@selector\\((\\w+)\\)"
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)\\s+\@selector\\((\\w+)\\)"
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)\\s+\\@selector\\((\\w+)\\)"
$ search_grep "\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)\\s+selector:@selector\\((\\w+)\\)"
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:(\\w+)\\s+selector:@selector\\((\\w+)\\)\\s+name:(\\w+)\\s+object:(\\w+)\\]"
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$
$ blog_new_post regex-disaster
$
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:(.*?)\\]"
$
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*(.*?)\\]"
[[NSNotificationCenter defaultCenter] addObserver:tar selector:@selector(sel) name:nam object:nil]
[[NSNotificationCenter defaultCenter] addObserver:tar selector:sel name:nam object:nil]
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*(.*?)\\s*\\]"
[[NSNotificationCenter defaultCenter] addObserver:tar selector:@selector(sel) name:nam object:nil]
[[NSNotificationCenter defaultCenter] addObserver:tar selector:sel name:nam object:nil]
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*nil\\s*\\]"
[[NSNotificationCenter defaultCenter] addObserver:tar selector:@selector(sel) name:nam object:nil]
[[NSNotificationCenter defaultCenter] addObserver:tar selector:sel name:nam object:nil]
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*nil\\s*\\]"
[[NSNotificationCenter defaultCenter] addObserver:tar selector:@selector(sel) name:nam object:nil]
[[NSNotificationCenter defaultCenter] addObserver:tar selector:sel name:nam object:nil]
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*nil\\s*\\]" "NC_ADD\\(\\g<1>, \\g<2>, \\g<3>\\)"
$
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*nil\\s*\\]" "NC_ADD\\(\\g<1>, \\g<2>, \\g<3>\\)" ""
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*nil\\s*\\]" "NC_ADD\\(\\g<1>, \\g<2>, \\g<3>\\)" 0
[[NSNotificationCenter defaultCenter] addObserver:tar selector:@selector(sel) name:nam object:nil]
[[NSNotificationCenter defaultCenter] addObserver:tar selector:sel name:nam object:nil]
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*nil\\s*\\]" "NC_ADD\(\\g<1>, \\g<2>, \\g<3>\)" 0
[[NSNotificationCenter defaultCenter] addObserver:tar selector:@selector(sel) name:nam object:nil]
[[NSNotificationCenter defaultCenter] addObserver:tar selector:sel name:nam object:nil]
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*nil\\s*\\]" "NC_ADD(\\g<1>, \\g<2>, \\g<3>)" 0
$
$ search_grep "NC_ADD\\(.*?\\)"
$ search_grep "NC_ADD\\(.*?\\);"
$ search_grep "NC_ADD\\(.*?\\);\\s+NC_ADD"
$ search_grep "(NC_ADD\\(.*?\\);)(\\s*?\n)+(\\s*NC_ADD)"
$ search_replace "(NC_ADD\\(.*?\\);)(\\s*?\n)+(\\s*NC_ADD)" "\\g<1>\n\\g<3>"
$ y
$
$ search_grep "(NC_ADD\\(.*?\\);)(\\s*?\n)+(\\s*NC_ADD)"
$ search_grep "(NC_ADD\\(.*?\\);)(\\s*?\n){2,}(\\s*NC_ADD)"
$ search_g "(NC_ADD\\(.*?\\);)(\\s*?\n){2,}(\\s*NC_ADD)"
$ search_replace "(NC_ADD\\(.*?\\);)(\\s*?\n){2,}(\\s*NC_ADD)" "\\g<1>\n\\g<3>"
$
$ search_grep "\\[NSNotificationCenter"
[[NSNotificationCenter defaultCenter] addObserver:tar selector:sel name:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotification:notif]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotification:notif]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
[[NSNotificationCenter defaultCenter] removeObserver:tar]
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s+addObserver:\\s*(.*?)\\s+selector\\s*:\\s*@selector\\s*\\((.*?)\\)\\s+name:(.*?)\\s+object:\\s*(.*?)\\s*\\]" "NC_ADDO(\\g<1>, \\g<2>, \\g<3>, \\g<4>)" 0
$ search_replace "(NC_ADD\\(.*?\\);)(\\s*?\n){2,}(\\s*NC_ADD)" "\\g<1>\n\\g<3>"
$
$ search_replace "(NC_ADD\\(.*?\\);)(\\s*?\n){2,}(\\s*NC_ADD)" "\\g<1>\n\\g<3>" 0
$ search_replace "(NC_ADDO?\\(.*?\\);)(\\s*?\n){2,}(\\s*NC_ADD)" "\\g<1>\n\\g<3>" 0
$ search_replace "(NC_ADDO?\\(.*?\\);)(\\s*?\n){2,}(\\s*NC_ADD)" "\\g<1>\n\\g<3>" 0
$
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotification\\s*:\\s*(.*?)\\s*(.*?)\\s*\\]" "NC_POSTN(\\g<1>)" 0
[[NSNotificationCenter defaultCenter] postNotification:notif]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotificationName\\s*:\\s*(.*?)\\s*(.*?)\\s+object\\s*:\\s*nil\\s*\\]" "NC_POST(\\g<1>)" 0
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotificationName\\s*:\\s*(.*?)\\s+object\\s*:\\s*nil\\s*\\]" "NC_POST(\\g<1>)" 0
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotificationName\\s*:\\s*(.*?)\\s+object\\s*:\\s*(.*?)\\s*\\]" "NC_POSTO(\\g<1>, \\g<2>)" 0
[[NSNotificationCenter defaultCenter] postNotification:notif]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
$
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotificationName\\s*:\\s*(.*?)\\s+object\\s*:\\s*(.*?)\\s*\\]" "NC_POSTO(\\g<1>, \\g<2>)" 0
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotificationName\\s*:\\s*(.*?)\\s+object\\s*:\\s*(.*?)\\s*\\]"
[[NSNotificationCenter defaultCenter] postNotification:notif]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
$ search_grep "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotificationName\\s*:\\s*(.*?)\\s+object\\s*:\\s*(.*?)\\s+userInfo\\s*:\\s*(.*?)\\s*\\]"
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*postNotificationName\\s*:\\s*(.*?)\\s+object\\s*:\\s*(.*?)\\s+userInfo\\s*:\\s*(.*?)\\s*\\]" "NC_POSTOU(\\g<1>, \\g<2>, (\\g<3>))" 0
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
$
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*removeObserver:\\s*:\\s*(.*?)\\s+object\\s*:\\s*(.*?)\\s+userInfo\\s*:\\s*(.*?)\\s*\\]" "NC_REMN(\\g<1>, \\g<2>)" 0
$
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*removeObserver\\s*:\\s*(.*?)\\s+name\\s*:\\s*(.*?)\\s+object\\s*:\\s*nil\\s*\\]" "NC_REMN(\\g<1>, \\g<2>)" 0
$
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*removeObserver\\s*:\\s*(.*?)\\s+name\\s*:\\s*(.*?)\\s+object\\s*:\\s*(.*?)\\s*\\]" "NC_REMNO(\\g<1>, \\g<2>, \\g<3>)" 0
[[NSNotificationCenter defaultCenter] removeObserver:tar name:nam object:obj]
$
$ search_replace "\\[\\[NSNotificationCenter\\s+defaultCenter\\]\\s*removeObserver\\s*:\\s*(.*?)\\s*\\]" "NC_REM(\\g<1>)" 0
[[NSNotificationCenter defaultCenter] removeObserver:tar name:nam object:obj]
$
$ search_grep "NC_REM\w*\\(.*?\\)"
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
[[NSNotificationCenter defaultCenter] postNotificationName:nam object:obj userInfo:uInfo]
[[NSNotificationCenter defaultCenter] removeObserver:tar name:nam object:obj]
[[NSNotificationCenter defaultCenter] removeObserver:tar name:nam object:obj]
[[NSNotificationCenter defaultCenter] removeObserver:tar name:nam object:obj]
$

Regex Disaster

It was such a painful lesson, almost as painful as my previous bash lesson, only mildly less awful.

Le me once wanted to write pretty bash code:

1
2
~$ var=5    # Ugly!
~$ var = 5  # better...

… Only to realize that the second line is an error. The script I was modifying was not through interactive shell, so I had no idea what is was throwing errors… Till this day, whitespace haunts me in my sleep.

As for the regex part, it was this:

1
regex = r"(?:.*\n.*){0, 3}"

This looks like a perfectly healthy regex expression, except that it is not. Adding that extra space within the braces made the whole thing break and produced unpredictable results. Don’t do that.



Event Dispatcher

A special post is happening this time, and it is a video! We will explore the new cocos2d-x Event Dispatcher, and how to use it as a replacement for CCNotificationCenter.

Without further ado:

Here are some relevent code snippets:

1
2
#define gEventDispatcher Director::getInstance()->getEventDispatcher()
#define NC_ADD(target, notif, handler) gEventDispatcher->addEventListenerWithSceneGraphPriority(EventListenerCustom::create(notif, handler), target);

Technological Lust

I grew up reading that lust is one of the deadly sins, but according to wikipedia, it can take many forms, including lust for knowledge, which is good, right?

I just got inspired to spill what is in my head and write about the tons of things I want to learn and try doing, so here it goes:

Haskell Game

You are not a programmer if you haven’t tried doing any functional programming. Actually, you can be, I was just exaggerating.

The premise is that functional programming is a new way to tackle programming problems and bends your thinking from looking at thing imperatively to another holistic view (I think).

I haven’t tried functional programming yet, and hence the idea of writing a game in Haskell.

Web Development / Ruby

I really wish I set some time aside and refactor my whole blog such that I know exactly how each and every thing works. After that, begins the fun of importing different frameworks and writing Ruby scripts for Octopress to streamline the process even more and make it awesome.

Cocos2d-X / Qt

I am already contributing to Cocos2d-X, but they seem to be interested in implementing a Mac client for the Cocos Studio, and it would be awesome if I can work on that. What would be even more awesome if I were to make it in Qt and make it multiplatform, while learning the Qt framework (since I am sick of the stupid Cocoa framework).

Pixel Art

I have started learning pixel art for a while, and abruptly stopped :( I need to get back to that..

Conclusion

Doesn’t look like much, actually!! Need to get serious about stuff.


Rant

I had this urge to just write a blog post, but don’t exactly know what to write about… Something broke along the way, I should be blogging like twice a day on average.

Anyways, let me see what should the first topic be…

Refactoring

I have been spending most of my extra energy refactoring the code I am working with at work. Some code hasn’t been visited since 2012, and I am just looking at the code, and I am thinking … “I have to understand what this does”. You see, you can’t really go into the flow state without a full clear idea of a macro perceptive of what you are working on.

Let’s track back a bit, I am saying too many things…

One, the flow state. You can only be truly productive if you enter this state. In order to enter this state, you need a clear goal, and very strong understanding of the work that has to be done. Basically, there is no flow state when you are just staring at the screen trying to understand something.

So, while I am looking around understanding code, I come across old code, which of course, is “bad” in terms of the current state of the project. Instead of enduring the pain of understanding the code, I go ahead and refactor it as well, so my future self, or other programmers don’t endure it, as well.

The process of refactoring is awesome because it actually allows you to enter the flow state even though you don’t understand the code, and you are trying to understand it! HOW?!

Let me pull a real example:

1
2
3
4
5
6
7
8
9
10
11
12
13
// FROM
[UIView animateWithDuration:1.6
                 animations:^{
                     dispatch_async(dispatch_get_main_queue(), ^{
                         int64_t delayInSeconds = 1500; //milliseconds actually
                         dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_MSEC);
                         dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                                [self doSomething];
                        });
                     });
                 }
                 completion:^(BOOL finished) {
}];

Anyways, this is code that hasn’t evolved as fast as the project.

So, while in complete focus, you see that the code is in dispatch_asyc, and then another dispatch is made. Obviously, we don’t need both, so BAM. Get rid of the outer async call.

Then, you see the milliseconds actually comment, and you simply rename that variable, and delete the comment. It’s a systematic process. You just apply what makes sense. Now, you got rid of that async call and useless comment.

Finally, you realize the delay can be added to the animateWithDuration call, and after you do that, the code doesn’t work anymore! You go into doSomething, and voala! There is another animateWithDuration call, and that’s why it didn’t work.

All this, as I mentioned, is systematic, and you can easily submit to the flow, and before you realize it, you have this code instead:

1
2
3
4
5
// TO
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
{
    [self doSomething];
});

Now, if anyone dares looks me in the eye and says refactoring is a waste of time, I’d probably lose hope in that individual’s future.

Yes, this is real code I dealt with.

Google Tag Manager

Because, why not?

Recently, I was asked to implement Google Tag Manager in our application for marketing purposes, and I’d like to share my thoughts on this beast.

We haven’t used it much, but my initial thought is.. WOW.

This beast is like a container for your “tags”. A tag is basically an addon that drives your application. This addon can be other apps, custom data, … you name it! All managed from a single slick web interface over at google’s website.

So, after integrating your app with GTM, all you have to do as a developer is deal with this single SDK! The powers it gives you are:

  1. Pull custom data from backend. (Customization)
  2. Integrate with apps on the fly. (AdWords, analytics, .. etc.)
  3. Manage container versions, and be backward compatible!

Yeah, it’s pretty darn awesome. Will post later how it actually performs, though.

Decorator Pattern

I made use of the decorator pattern, so I might as well share that! :D

The premise of the decorator pattern for GUI systems is that .. You decorate the base view with decorators! So, the decorator I wrote simply applies a “popup” effect, by rounding the corners and adding a close button at the top left corner.

Pretty neat stuff! Now, any view you want to show as a popup is developed independent of this aesthetic look… Truly awesome stuff. MUCH, MUCH better than the naive approach of “Uh, yeah, let’s just subclass”.

Reading

Opposed to my lack of blogging recently, I have been reading… and reading A LOT. If I am walking.. Just walking, and not responding to emails, whatsapps, … etc, I am reading something. To the point that, I walked the whole Mall of the Emirates back and forth to take a passport pic, and while walking, I finished 5 chapters of my book.

I am not sure it’s good or bad, but it’s sure productive! Walking is now coupled with reading, and is no longer irritating. Sometimes while walking, some (me) get affected by their surrounding negatively, and could flip their mood completely. But reading, and immersing yourself in that book instead of what’s around you, … is bad, actually. One ought to be more social than that…

Food

Without feeding, we can’t survive… Wait, wth am I writing! OK, I need to go eat .. NOW.

Conclusion

I like blogging… I wish people would blog more often, and especially people like Abdullah Al-Shalabi. Freaking awesome stuff he puts up on those posts.


Cocos2d-X v3

If you haven’t read the cocos2d-x forums yet, there has been a radical change to the cocos2d-x github repo. Basically, the team decided to abandon ship! No, they just moved from the develop branch to the new, shiny v3.

It wasn’t that bad of a migration for me. All I needed to do is follow the instructions in the post referenced above, and apply my own patches and changes. One issue was converting Point to Vec2… I mean… Whatever. Cocos should be renamed to something more meaningful if they aren’t gonna use ANY Cocoa conventions!!


A Challenge

I am collaborating on a iOS project, and the team is using Xcode. The issue with Xcode is that it doesn’t do any kind of #import management.

The challenge is to write a script that simply checks the import and searches the file for that class. If not present, remove that import. This is naive, since that imported file might contain other headers, variables, … etc, that are needed, but for the purposes of getting this over quickly, we will overlook that part.

5:11 pm: START!

Obviously it’s gonna be python…

5:16 pm:

Instead of defining a function that taken a path pointing to a file, I should make it take a string, so I can easily test it when I am done!

1
2
def clean_imports(file_contents):
    # stuff

5:24 pm:

I am slow… And I wish I used PyCharm for this, not sublime. Anyways, v0.0.0.1 is working!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
import re

def clean_imports(file_contents):
    """"""

    import_regex = re.compile(r'#import\s+"(\w+)\.h"')
    check_regex_raw = r"{}[^(\.h)]"

    all_classes = []
    for match in import_regex.finditer(file_contents):
        all_classes.append(match.group(1))

    print repr(all_classes)

clean_imports('#import "thisisatest.h" akdjsf a;ksldfj')

5:33 pm

I think it is done, and ready to be hooked with a “crawler”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import os
import re

def clean_imports(file_contents):
    """"""

    import_regex = re.compile(r'#import\s+"(\w+)\.h"')
    check_regex_raw = r"{}[^(\.h)]"

    all_classes = []
    for match in import_regex.finditer(file_contents):
        all_classes.append(match.group(1))

    for klass in all_classes:
        check_regex = re.compile(check_regex_raw.format(klass))

        if not check_regex.findall(file_contents):
            file_contents = file_contents.replace(klass, klass + "NOTUSED")

        else :
            print repr(check_regex.findall(file_contents))

    print file_contents

clean_imports('#import "thisisatest.h" akdjsf a;ksldfj thisisatest ')

5:37 pm

Time to test!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import os
import re

def clean_imports(file_contents):
    """"""

    import_regex = re.compile(r'#import\s+"(\w+)\.h"')
    check_regex_raw = r"{}[^(\.h)]"

    all_classes = []
    for match in import_regex.finditer(file_contents):
        all_classes.append(match.group(1))

    for klass in all_classes:
        check_regex = re.compile(check_regex_raw.format(klass))

        if not check_regex.findall(file_contents):
            file_contents = file_contents.replace(klass, klass + "NOTUSED")

        else :
            print repr(check_regex.findall(file_contents))

    return file_contents

if __name__ == "__main__":
    walk = os.walk(".")

    for dirname, dirs, files in walk:
        src_files = [x for x in files if x[:-2] in [".h", ".m"]]
        for afile in src_files:
            filepath = os.path.join(dirname, afile)
            with open(filepath) as f:
                contents = f.read()

            new_contents = clean_imports(contents)
            with open(filepath, "w+") as f:
                contents.write(new_contents)

5:43 pm

Tested… found so many bugs… Try to spot them. Time to run this beast!

5:48 pm

Fail. This is the worst idea I had ever. Xcode refused to compile anything when it saw the #import “blahblahUNUSED.h”. The premise was to comment it out type of deal, but it doesn’t work like commenting it out.

Need to revisit this later.

Conclusion

Whatever.. It was a nice exercise anyways.


Stand In

I am working on this credentials dialog where you would put a username/password, and then wait for things to happen with the backend. Obviously, I need some kind of loading indicator along with a cancel button.

The first thing is, how will I implement this? Assuming we don’t want to close the dialog, the most obvious and naive solution is to remove all views inside the dialog, and show the loading and cancel button. Other possible solutions that beat around that bush are there, but there is a much better solution.

Stand ins! A stand in is basically a way where you quickly swap the original thing with a replacement without anyone noticing. Movie actors due it all the time. You are watching the star riding this car, and all of a sudden he is jumping out of the car. The actual guy who jumps out of the car is a stunt man who stood in the star’s place!

Anyways, the idea of a stand in is to reduce the logic and complexity in the application, as well as promote reusability. If we implement the loading dialog as a stand in, it means that it is a separate component that can be used a lot of other places as well.


Over Gitting It

A guy once said, “You can never have enough of git”. Clearly he is mistaken, as I have completely overkilled it with the use of git for a mundane task, solved by much easier means.

There is this page in Humble Indie Bundle, that shows you your downloads, and you can switch between direct download and bit torrent. I wanted to know which downloads are only available as direct download.

Ding! My brain orders me to copy the list of direct downloads to a file, initialize a git repo, commit, replace the contents with the bit torrent downloads, check the diff for missing links.

After doing that, Mr. Jim gives another solution through diff. That reminds me how he praised that command in the past, but I never actually used it, which is probably why I completely forgot about it.

The ultimate answer, however, was to simply to highlight the list, switch to Bit torrent and back to direct downloads, then deselect. Now, the missing downloads from the bit torrent page should be highlighted!


Less is Better

Because of all the time I spent looking at other people’s code, using other people’s code, and simply writing damn code, it became quite rare for me to find good Objective-C I am not already aware of. Maybe I am not looking the right places, but that’s how it is.

Today, however, I found a new awesome practice that got me super excited and blogging once more.

Restrict and Defend!

When writing code, good code, always restrict and defend!

Access Denied

What I mean by restrict is to disable any behavior that external code might impose on your code in a way you have not meant for it to be. An example will make this crystal clear.

Let’s say you have a singleton class. In most languages that have sane constructors, you can easily declare the constructor as private and you are all set. External code can’t instantiate the singleton, and can only access the shared instance. We can’t do that in objective-c, but here is what we can do:

1
- (id)init __attribute__((unavailable));

This marks the init method with an unavailable attribute so external classes cannot instantiate an instance. I would take this a step further, and mark the +[NSObject new] method as unavailable, as well.

I know, Mr. Smarty Pants, the caller can easily work around this using performSelector: or even casting to id, but all we have to do, really, is throw an exception in the init method, and use another init for our internal use.

Put Up Those Defenses!

As for defending, it is the practice of validating parameters passed to your objects. The simplest defense is NSParameterAssert, which asserts that the parameter passed is not nil. You would want to use that when you absolutely need a parameter to be a valid, non-nil value.

Other defenses can be set up using NSAssert by validating strict assumptions you are making about the passed objects.

Conclusion

They say less is more. In our case, less is more and even better.


Binary, Or Not!

One of the terminal scripts that I heavily use is the search and replace script. It simply searches for occurrences of a string, and highlights the results in terminal. You can optionally choose to replace that string with something else.

In any case, it caused me a lot of headaches and unnecessarily slowed down the search when the script scanned binary files. Not only is it not useful to search those files, but the binary can easily corrupt if we replace something in it by mistake.

It is unfortunate that python doesn’t seem to have a library included that solves this issue, but thankfully pypi has the answer.

binaryornot

Talk about originality, eh? binaryornot is a very simple module that serves the purpose of detecting whether a file or string is binary. I have no idea how it internally works, but it gets the job done:

1
2
3
4
5
# Import the check module, and name it something more relevant.
from binaryornot import check as bcheck

if not bcheck.is_binary(pathToFile):
    # Do the search!

Simple, and super handy.

Conclusion

I love python, and dream that one day I can talk python with other people.


Validate Your Assumptions

When working with a scripting language like python, it is so awesome how easily you can test your assumptions or experiment with module. You simply launch terminal, go into python’s interactive interpreter and you test to your heart’s content.

What about iOS apps?

As far as my Google ship sailed, I couldn’t find anything solid. People always recommended starting a new project in Xcode and doing stuff there.

Well, what I came here to say is, I will probably use this approach as my second debugging step. The first debugging step is simply using the interactive console to dump the variables and see if anything looks awkward.

It may seem like an overkill to create a new project and build the setup to test something, but in most cases it’s probably not. The freedom to focus on a single component in the project rids you of having to worry about other code affecting the component’s behavior. It also gives you the perfect environment to further explore and learn more about the component, by iterating quickly with the fresh project.

Conclusion

This was probably a useless rant for the sake of writing a blog post today, and not falling behind.


Unity So Far

If I had a choice, I’d go back to cocos in a blink of an eye. It’s is so unfortunate that the conditions of out team forces us to use Unity (it is mainly artists and designers), as well as the fact that, well… The freakin game is in 3D! So, Unity is the only feasible solution for our needs…

Animation States

I ran into this weird and super annoying issue in my very first Unity game, which is dead simple! Actually, make that two weird issues.

The Any State

When setting up an animation in Unity, there is a convenient “Any State” block that allows you to transition to a state from any other state. The obvious need for this is the death animation state, which can occur at any given time.

Believe it or not, when you set a condition to move to transition from the “Any State”, it also includes the state you just transitioned to!!

“What do you mean?”

Adding a transition to the “death” state from “Any State” using a condition like “if isDead is true”, will cause the animator to transition from whatever state to the death state, and then transition from the death state to itself as long as the isDead is still evaluating to true!! ლ(ಠ益ಠლ)

Atomicity

Animation transitions created are atomic by default, i.e. they cannot be interrupted. So, when you have a player banging on the keyboard, and you are using the “Any State” explained above, you have a serious problem.

Since the “Any State approach” requires you to reset the condition after transitioning, what I did was simply:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Update()
{
    // update animator (Stupid transition from any state includes current state -_-")
    int heading = CalculateHeading(horizontalInput, verticalInput);

    if (heading != previousHeading)
    {
        anim.SetInteger("direction", heading);
        previousHeading = heading;
    }
    else
    {
        anim.SetInteger("direction", -heading);
    }
}

Looks good to me. Set the integer, and on next update clear it, and so on… Not so fast there, buddy. Remember that talk about atomicity? Well, even if you freakin turn it off, the transition still cannot be interrupted >__<. That is to say, if you do “transition to x, transition to y, stop” fast enough, the transition to y will never happen!

I really don’t want to explain this again, please see my stackOverflow question

Conclusion

Don’t sweat it… As long as Unity enables you to achieve your goal, endure it like a women would endure a delivery to see the smile of her child… Saying that felt so weird.


The Quiz

The Quiz

You have these numbers at your disposal:

1
1, 3, 5, 7, 9, 11, 13, 15

use them, with repetition, to make the following expression evaluate to true:

1
__ + __ + __ + __ + __ = 30

Solution

What I naturally did was:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def all_combos(arr, result):
    """"""

    if len(result) == 5:
        if sum(result) == 30:
            print result
    else :
        for x in arr:
            new_result = result[:]
            new_result.append(x)

            all_combos(arr, new_result)


available_numbers = range(1, 16)[::2]

all_combos(available_numbers, [])

Which gave no solutions at all…

So I raged at the person who gave the question, and they replied:

Dude, there is no way you can add odd numbers an odd number of times, and get an even number. That’s the real solution.

Conclusion

Ever heard of the “Helicopter Approach”? Well, you should read about it.


Gmail Filters

It seems inevitable that once you start using GitHub seriously, you run into this issue where you just get overwhelmed by the number of emails sent in a single hour. It also gets distracting and annoying when you just don’t have the time to go over them, and need to see everything else.

That’s where Gmail filters come into place.

It is probably an ancient concept that is widely used in the developed countries, but for a developing county, emails where never our thing. “MSN” was. That caused us to be less interested in investing time organizing our inbox, and more interested in changing our profile pictures and status messages on IM clients.

(Note to you youngsters, MSN was what we called all IM services, which was only MSN initially, then GTalk, … etc. “Let’s chat on google’s MSN!” was a common phrase.)

The Filters

Setting them filters is super easy, and convenient. After going to the gmail web app, just search for the pattern of emails you want to filter. It should update the view to show you the result. You can use this to validate your search query. After that, click the small gray arrow next to the search button, and choose “create filter from search”. Le Done.

Conclusion

Stop allowing your valuable time to be slowly consumed by all those emails that you don’t need to see immediately. That especially applies when you are at work, or in the mood to do great things. This will come in handy.