MAZYOD’S
DEVDIARY

Blabbering on, and on, and on…

QRR I

QRR is yet another series, and it stands for “Quick, Random Rant”. Please don’t make me catch you translating QRR without adding that comma. Thanks.

The premise is to just push myself to blog more, so I open the editor without a topic in mind, and start typing.

The Topic

What comes to mind is something I’ve been recently working on, and that is of course, Cocos2d-x. Cocos is an excellent library, but I have learned the hard way that it was the worst possible choice for me. Let me enlighten you why.

It’s C++

C++ is a grownups language. It’s arguably the most powerful language, but it requires you to be mindful about every freakin detail that you write. Writing my game in such a language, over the span of two years, is a nightmare. I learned so many things, and realized how many mistakes I made in the past, as I desperately attempt to fix them.

That characteristic of C++ also implies that you have to write everything yourself. You need an observer pattern? Write it! You need a string formatter? Write it! Seasoned C++ programmers might argue that boost C++ is the way to go, since it implements most of these missing features from the language, but I only realized that after I decided never to write a personal game in C++ again.

It’s Turbulent

Almost every new version of the library comes with changes that break your sufficiently-complex project. Whether it is as simple as deprecations, all the way to core engine behaviors. These changes make a long lived project mostly about maintenance rather than focusing on making the game.

It’s Buggy

No matter what you hear, Cocos2d-X is supported by the community, and is bound to be buggy. It’s not horribly buggy, but you’ll find yourself looking for solutions to the engine every now and then, and you can’t afford that when running a one man show, now can you.

Conclusion

Well, am happy that I actually contributed something today, and by all means, I am not saying stay away from Cocos2d-x! Just be mindful about those issues, and choose a Javascript/Lua binding approach maybe. As for me, I’ll test drive the JS binding for my next game, and try a few other promising engines.


On APNS

Recently, I went back to my undocumented project to implement a few new features that are related to the recent change the the push notification API on iOS 8. I fell into a trap, that I only recalled I’ve fell into it before after falling into it again >__<

Push Notifications

Apparently, you should only call unregisterForRemoteNotifications on rare circumstances. The reason for that is, Apple is saying that you should tweak the push notification behavior on the server side rather than unregistering and re-registering based on the user settings.

An important note here is, the user is able to completely block push notifications from the app through the iOS settings.app. That is how Apple wants users to behave:

Don’t make users disable and enabled push notifications through the app. Instead, there is a single place to manage all notification settings for all apps, and that is in the settings app.

Of course, that quote isn’t from Apple, but I am just shoving words in their mouths from what I can conclude from the docs.

iOS 8

If you haven’t heard, Apple has transitioned in iOS 8 to UIUserNotification APIs, that consolidate the UILocalNotifications and UIRemoteNotifications APIs. It’s nice, and it completely lacks the unregister method discussed above. So, you are forced to do things the Apple-way.

Conclusion

I really hope Apple just stops everything for a whole year, and stabilize iOS, Mac, Swift, Xcode, and all the other new goodies they threw at us. They are all pretty awesome, but lots of issues are surfacing with these new changes.


Spine Skeleton Data Caching in Cocos2d-X

Introduction

While integrating the amazing Spine editor by esoteric software with my cocos2d-x game, I ran into an issue where the game would take a while to load. Since the only thing I changed since the last time I tested the game was add new spine animations, that was most likely the cause of this performance hit.

By following the definition of:

SkeletonAnimation::createWithFile(...);

I realized the runtime was loading the file everytime without any sort of caching going on. Mature frameworks most certainly take care of this task automatically for you (for example, UIKit’s convenient method in the UIImage class that we all use, imageNamed:). Alas, that had to be solved by us, but thanks to open source software, it’s as easy as pie.

The Meat

So, once you see the implementation of SkeletonAnimation, you realize that it creates a SkeletonRenderer object with the named files. That class loads the files into a spSkeleton object, which holds the parsed data in the data member. data is const, and according to the runtime diagram, it should be fine to reuse.

So, here is the solution!

static Map<std::string, SkeletonRenderer *> skeleRendererCache;
if (!skeleRendererCache.at(filename))
{
    auto skeleRenderer = SkeletonRenderer::createWithFile(jsonFile.c_str(), atlasFile.c_str()/*,  0.1 */);
    skeleRendererCache.insert(filename, skeleRenderer);
}

auto cacheData = skeleRendererCache.at(filename)->getSkeleton()->data;

SkeletonAnimation* skelly = SkeletonAnimation::createWithData(cacheData);
skelly->setSkin(skin.c_str());
skelly->setSlotsToSetupPose();
skelly->setAnimation(0, "idle-simple", true);

skelly->update(0);

return skelly;

Conclusion

All hail open source, for which without, this task would’ve been boring, dull, and time consuming!


Amazon EC2

Introduction

As the case is with most developers, I decided to move away from GoDaddy’s PHP hosting, and move to Amazon EC2, because that’s what the cool kids do these days. I have to say, though, if you just want to get shit done, GoDaddy was 100 times less painful. However, after deploying on GoDaddy, I still felt novice and didn’t learn a thing… So, for the sake of improving and learning, EC2 is way better.

Pandora’s Box

The first thing I had to do was run our site on this shiny new server. My choice of poison was Flask. Honestly, bottle would’ve served me just as well, but in any case.

I got the site up and running in no time on my local machine. The horrors started after I wanted to deploy.

Lesson #1: Permissions

If something doesn’t work on Linux, check your permissions.

After following a tutorial step-by-step and setting up apache, along side the wsgi configuration, I got really weird errors from the server. I looked up the logs, nothing. It wasn’t even logging properly.

Banding my head for hours, and stripping down the application to a bare minimum, I finally stumbled upon a solution that suggested checking your permissions. Now, the first thing I do is permissions, before checking if I missed a semi-colon.

Lesson #2: Invest in the Best

Beyond your first option, is a best option.

The wsgi thingie worked! I was happy to see all the things showing when I navigate to our site. It was a happy moment, yet too early to celebrate.

Our site provides a service that needs to be up-to-date on daily basis. Hello, Daemons.

Daemons was a very new topic to me, and the whole Linux thing was, too. I am no sysadmin, and it was torture to work as one. Reality is, I had to do it, anyway.

Code monkey search online for resources…

Code monkey find init.d daemons…

Code monkey thinks this is the best way…

Code monkey wastes hours messing with the syntax..

Code monkey finally searches for alternatives and finds the awesome Upstart.

With upstart, it was as easy as pi to get the daemon running, and it was time to actually put together the daemon script!

Lesson #3: Log is your friend

No matter what application you are writing, just make sure you have logging setup properly right off the bat.

I didn’t really learn that logging is your friend from this experience, but I did invest a lot of time setting up proper logging. What is a better logging mechanism than to get an email when something happens? Get an SMS!

Well, I didn’t setup SMS notification (yet), but email logging is pretty cool by itself. The problem is, python’s default mail handler, SMTPHandler doesn’t have TLS capabilities integrated, so it didn’t work with Gmail accounts. Searching for solutions online, they didn’t seem to work properly for me. That’s when I looked outside python.

I was unfortunate to try and setup email logging through postfix initially, which is a freakin overkill.

It didn’t get any better when I found (sSMTP)[https://wiki.archlinux.org/index.php/SSMTP]. After installing ssmtp, it was easy to send emails through terminal, but I had to go through all the subprocess ride to get something working, and it didn’t work as expected…

After trying to fix it for a while, I went back to look into python again, and found smtplib. This worked perfectly, alongside a simple producer/consumer setup, using Queue, it was working like a charm.

With all that in place, one can now have a little piece of mind knowing that if the server chokes, we’ll get notified right away.

Lesson #4: Automation

Computers are good for two things: Crunching numbers and repetition

I can’t really imagine anyone trying to configure a server and develop on it without having some sort of scripting language in their toolset. If you’re spending more than 1% of your time not writing business logic and solving problems, your process is not automated enough.

That doesn’t only include scripts to make your workflow easier and faster, but also loggers to identify problems quickly and unit testing / regression testing.

Conclusion

If you ever decided to build your backend service on Amazon EC2, make sure you’re doing it for the right reasons. There are many other better and easier alternatives, otherwise, prepare to invest lots of time in this.


Synchronized

Introduction

Whenever I write something about synchronization, I am required, by law, to reference this picture:

If you don’t get it, just let it slide.

Disclaimer: Vim/emacs users, stop reading. Now. Probably.

The Problem

As with all useful articles, we are ultimately aiming to solve a problem. The problem we would like to amend is the slow process of developing projects on a remote sever.

Hence, what we are trying to achieve is Simple, iterative process of developing projects on a remote server

The Story

After launching a Amazon EC2 Ubuntu instance, I moved all my projects to the server in order to run them, and they instantly broke. Thankfully, I had setup a logging mechanism, so I realized what the problems were, but now I need to fix them!

I launch my favorite IDE, PyCharm, and fix those issues, and commit to the VCS. Only problem now is, I need the server to get those changes!

First thing I did was, I would ssh into the server, navigate to the project root, and pull latest, execute a deploy script. This deemed very mundane and time consuming!

I then tried utilizing an old script I had, which uses scp, to transfer my files. The problem now was, scp was transferring everything, every single time. Not only that, but I no longer need the .git directory to be sent, as well as all the patterns that are specified in the .gitignore! Something had to change. It was time to learn something new.

The rsync

After searching on how to exclude files from scp, the answer was: “You can’t. Use rsync, instead”. Best part about this is, rsync comes with so many more benefits other than excluding files, as we we’ll see now.

rsync’s beauty in this context can be described in three points:

  1. Effeciency: Only sends the new/changed files! Doesn’t transfer the whole directory every single time, like scp did.
  2. Control: Using --include, --exclude, you can easily control what gets synced, and what doesn’t.
  3. Organization: By specifying the --delete options, files deleted locally will also be deleted from the remote directory.

Needless to say, that’s all I ever wanted.

The Scripts

Now, let’s take a look at how this works:

def cmd_ec2_rsyc_project(project_path="."):
    """Syncs the project path with the ec instances projects dir, optionally invoking 'deploy.py' remotely"""

    project_path = resolve_path(project_path)
    # Important: Make sure we have a trailing slash! Read more:
    # http://bit.ly/1rYK94U
    project_path += "/" if not project_path.endswith("/") else ""

    # Resolve the remote path
    project_name = os.path.basename(project_path[:-1])
    target_project_path = os.path.join(REMOTE_PROJECTS_DIR, project_name)
    remote_path = REMOTE_ADDRESS + ":" + target_project_path

    # Read more about the extra options here: http://bit.ly/1rYK94U
    os.system("rsync -azP --delete --exclude '.*' {src} {dst}".format(
        src=project_path, dst=remote_path
    ))

    if not os.path.exists(os.path.join(project_path, "deploy.py")):
        return

    # Silver lining: Execute the deploy script after syncing
    os.system("ssh {addr} 'sudo python {script_path}'".format(
        addr=REMOTE_ADDRESS, script_path=os.path.join(target_project_path, "deploy.py")
    ))

Conclusion

With all that setup in the pythonic terminal, it’s as tasty as pie!


The Daily WTF III

In today’s wtf, we will looking at a very peculiar case.

The Fail

While going over the code, I noticed a very strange block. The programmer was constructing a JSON payload from available variables and then passing the payload to the visible view controller, like so:

NSString *vanityURL = params[@"vanity_url"];
NSDictionary *payloadParams = @{@"endpoint" : @"story/profile",
                                @"params" : @{@"vanity_url": vanityURL},
                                @"type" : @"story"};

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payloadParams
                                                   options:0
                                                     error:nil];

NSString *payload = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

params = @{@"feedbackPayload" : payload,
           @"user_vanity_url" : vanityURL,
           @"analytics_key": vanityURL,
           @"title": vanityURL};

I really don’t want to get into the details of where these hardcoded strings came from, or why the hell a JSON payload is created in the first place, but there is no limit to how bad code can be, apparently.

NOTE: I added newline separations for the reader to be able to read the code. It was actually all smushed together without any spacing.

… One more fun fact, this code lies in the infamously abused AppDelegate class.


A Post About Nothing

Inspired by an episode from Seinfled, I decided to make a post about nothing. Well, I do have to write something, so it will be an improvise of whatever comes to mind.

What Is Nothing

Some might argue that in programming we have null, which is nothing. However, if null is nothing, then what is void?

I think null in most programming languages is just a sentinel value, hence it is something. Although some languages, like python and swift, actually have “nothing”, which is the None type. If you have a function in python that returns nothing, and you try to assign the return to a variable anyway, that variable will hold None, which is literally nothing.

Is It Important?

It is very important to have this concept of a well defined “nothingness” in a language. If you have it, you can easily express the nothingness of something…

I mean, in a typical case scenario, we might have a method that returns an int. If for some reason that method might fail to calculate the return type, we would want to return something to indicate the calculation failure. In a language like objc, we use NSNotFound, which is just INT_MIN. But what if that value is a possible value returned by the method?

So, adding a nothingness provides a consistent way of expressing a no-value thing that the caller understands.

Conclusion

(null)


Singletons Hidden Poison

The singleton design pattern is an extremely convenient weapon to utilize in any software project, be it a game, app, or whatever. For many years, I used singletons, and slowly formed a mental image of how they work. Today, I realize how poisoned my code is because of these treacherous snakes.

Singleton Flaws

It is widely known that the main issue with singletons is that you need to make sure that you will ever need one object of the singleton class you’re creating.

Another issue with singletons is how they seep through the code, and are hard to clean up once created, hence most use cases, if not all, require that the singleton instance is never destroyed. This global access also promotes contention and tight coupling, which is bad ®.

The Poison

Moving on to the poison about the singleton pattern, it is actually part of the global access issue. After creating that singleton instance, one would be very tempted to access everything through that singleton instance. I’ll explain with the problem I fell into:

When writing a game, I made the GameScene a singleton instance, since the game has so many layers and sublayers (objects) hierarchy. So, initially the intention was pure. I just wanted an object deep within the hierarchy to be easily able to send messages to the GameScene if an action happened…

The problem started when I ended up using the singleton instance to fetch information about the game.. Instead of initializing a layer with the necessary data, I would just initialize it normally, and query the singleton for the data. Sooooo bad…

The main issue with this is … I can no longer test the components in separate/isolated context! The GameScene, along with all the layers that query it, have been tied by the chains of fate, and became this inseparable, monolithic component, which ended up being a burden on testing and maintainability.

Conclusion

When the use of singletons is necessary, try using dependency injection, but in general, avoid relying on them for immediate convenience, and do your job of properly designing the object hierarchy and data flow!


The Daily WTF II

This one is my favorite, and was the first wtf I fixed, because it was so bad…

The WTF

In iOS, we have view controllers, and the whole app is built around the concept of view controllers. Now, someone decided that if we are going to present a modal view controller, the view life cycle calls are no longer relevant, and they used a cached boolean for a check (not even bothering with self.presentedViewController) (/facepalm_all_the_way_to_the_back_of_my_skull):

- (void)viewWillAppear
{
    if (self.modalPreseted) {
        return;
    }

    [super viewWillAppear];
    // ... more stuff
}

- (void)viewWillDisappear
{
    if (self.modalPreseted) {
        return;
    }

    [super viewWillDisappear];
    // ... more stuff
}

Why Is It So Bad?

These methods are provided by UIKit, and we are overriding them. These methods are sacred, and are expected to execute the way they are designed to be executed.

As an iOS developer coming to the project, it’s hard and painful enough to learn the code base and the custom implementation, and now you expect me to unlearn UIKit, and learn those hacky ways that don’t even make sense?


How to Compose

In a previous post, I talked about the beauty of composition. Today, I want to extend on that with a beautiful enlightenment that I had. Lucky you, I am gonna share it, and you are reading it!

Breaking It Down

It is all about breaking those methods calls down!

Let’s assume you are building an application that authenticates with different services, like twitter, facebook, google, … etc. If you have this in your code, you’re doing it wrong (I used python because it’s easier to write):

class AuthManager(Object):
    def authenticateWithTwitter(self):
        ...

    def logoutFromTwitter(self):
        ...

    def authenticateWithFacebook(self):
        ...

    def logoutFromFacebook(self):
        ...

authManager = AuthManager()
if user.selection() == 'Twitter':
    authManager.authenticateWithTwitter()

elif user.selection() == 'Facebook':
    authManager.authenticateWithFacebook()

Now, notice how you can achieve a much more modular design with even better readability:

class AuthManager(Object):
    
    def __init__(self):
        self.twitter = TwitterService()
        self.facebook = FacebookService()

authManager = AuthManager()
authService = None
if user.selection() == 'Twitter':
    authService = authManager.twitter

elif user.selection() == 'Facebook':
    authService = authManager.facebook

authService.authenticate()

I know, I could’ve used getattr, but that’s not the point. The point is how we managed to break the long method name into a nicely composited object!! This is actually the obvious example, let’s see a bit more challenging one:

class Person(Object):
    
    def __init__(self):
        self.name = "Kirito"
        self.DOB = datetime.now() # whatever

    @property
    def age(self):
        """Compute age from DOB"""
        return ...

    def getLocalizedAge(self):
        """Return a localization friendly age"""
        return LocalizationManager.instance().localizeNumber(self.age)

    def getLocalizedDOB(self):
        """Return a localization friendly date"""
        return LocalizaitonManager.instance().localizedDate(self.DOB)

You can see it now, can’t you ;) YES!! This is bad, and should be changed to:

class Person(Object):
    
    def __init__(self):
        self.name = "Kirito"
        self.DOB = datetime.now() # whatever
        self.localized = PersonLocalizer()

    @property
    def age(self):
        """Compute age from DOB"""
        return ...

person = Person()
person.localized.DOB()

Conclusion

I don’t think I will ever write anything in the blog of more value than this post… I desperately needed this advice ages ago.


The Daily WTF

I just can’t take it anymore.. I have been quite conservative of some really wtf code, and it’s going on the blog form now on.

Apparently, we have these two methods in our class:

1
2
3
4
5
6
7
8
9
- (void)requestFacebookPermissionsWithCompletionHandler:(void (^)(NSArray *permissions, NSError *error))completion
{
    ...
}

- (void)requestFacebookPermissions:(void (^)())completionHandler
{
    ...
}

Here is the best part:

THEY SERVE COMPLETELY INDEPENDENT PURPOSES.

While refactoring the code, I did cleanups to the method names, so in the process, both these methods had the exact same name… Who in their right mind would do such a horrible thing…


The Beauty of Composition

On of the highly debatable problems that we come across as programmers is the classical inheritance vs composition problem. It haunts us as we try to figure out how to group duplicate code across multiple classes, and today the rant shall be about that.

Hierarchical

A language like Java uses the keyword “extends” to indicate inheritance. I love that, because it helps the code become more readable, and it becomes clear to any programmer what our class’s relationship is to its superclass.

From there, you just have to keep in mind that when you design your class hierarchies that any superclass within that hierarchy will impose itself as an “alias” to the subclass… I don’t think that was clear, so let’s see an example:

Let’s say we are designing a “View Controller” hierarchy. In UIKit, the developers decided to go with ViewController, then under that comes CollectionViewController, TableViewController, … etc. Notice that TableViewController can still be called a ViewController, so we say that ViewController is just an abstract alias of TableViewController.

Notice also how this imposes the type of hierarchy we have here. We are essentially making a controllers hierarchy based on the type of view they have. This isn’t a must, it’s just how developers of UIKit/AppKit decided to go.

That’s all nice and dandy.. The trouble starts creeping in when the developers want to extend these classes to provide their application-specific hierarchies.

So, in the problem I am having, we have a bunch of ViewControllers that are related to the login process. The duplicate code that we want to eliminate is related to the HUD loading indicator that we show when the authentication process starts, and then removing it when the authentication is complete.

The code I came across made the obvious approach of defining a LoginViewController superclass, and extended that class in the different login service (facebook, twitter, email). The only problem here is that some of the classes are TableViewController while others are not! So, if they all inherit from LoginViewController, they either all have to be TableViewController or plain ViewController, depending on what LoginViewController derives from…

Composite

Now, we reach the composite approach. In the problem described above, we simply inherit from TableViewController or ViewController in each of the login classes depending on the use case. This hierarchy matches what we see in UIKit so it is the best approach. How about the duplicate HUD code?

We simply have to define a new class, call it AuthHUDController. That class will then be instantiated in those classes in a single line of code, then some customization can be made to it per use case, giving us more flexibility.

Ideally, we would want to eliminate all duplicate code, including the instantiation of the AuthHUDController, but doing that without ending up with a weird and implicit implementation (using AOP or similar) is very tricky, and would probably be best avoided.

There is actually another composite solution, and that is to make LoginViewController a subclass of ViewController, then in the classes that were deriving from TableViewController we move the table view code to a new class, and make that a composite in the old class.

In any case, it’s both using the beauty of composition.

Conclusion

The problem ends up not being that difficult if we realized the above definitions and sticked to them!


Solving Programming Problems

At sourcebits, I realized that whenever our technical lead wants to convey an idea to the team, he would always do that through a visual graph. He would quickly put together an FSM diagram, a flowchart, or whatever to materialize his thoughts and make sure we can all clearly see his idea.

I thought that was cool, but didn’t quite do it myself because I work on my own project alone. The thing I realize now is that Joe, our tech lead, might’ve also used charts and graphs to organize his own thoughts and think about the problem, because I started doing that, and it’s insanely helpful!

Here is an example of a problem I am trying to solve:

As you can probably tell, this is the matchmaking process in the game, and using yEd, I can easily draw this FSM and make sure I account for all situations.

Now, I am stuck at that last state. If the user presses “accept” to the matchmaking, we poll the match status to see if the other user accepts. If the user’s device crashes, or the user kills the app, our game won’t be able to report that the user is no longer available, so we have to set the match state as INVALID after a certain amount of time…

Sounds simple, although it isn’t with the constraints I have. I can either have the client disconnect if a certain amount of time passed, but that doesn’t concern the client app. It should be as dumb as possible and just poll the match status. If that magically becomes INVALID by any other means, then we can close the dialog.

So, this “magical” way of invalidating the match… I can think of two ways of doing this:

One approach is to add a timestamp variable to the session, and each time the user polls the status, we have some logic in the backend checking the timestamp to determine if the match should be invalidated. The problem is that we don’t know exactly when the match state has switched from “looking for opponent” to “waiting for confirmation” (aka accept). We have to store the previous state and all that crap.

Another approach is to associate the timestamp with the match object, and check the timestamp from the match itself. This is easy to implement and the logic actually fits. Once we change the match state to WAITING_CONFIRMATION, we can set the timestamp then.

Conclusion

Try drawing diagrams for your problems, it will help you model a solution!!


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 :( …

Thank You, Knowledge Sharing People

This is a very detailed and organized article on integrating Jenkins with Xcode. Another important resource was this simple set of steps that helped me debug a few issues.

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:

$ 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:

$ 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:

class <#class#> : public <#superclass#>
{
    
public:
    
    static <#class#> *create(<#args-definition#>);
    virtual bool init(<#args-definition#>);
    
};
<#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

$ 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:

~$ 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:

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.