Commit #9: Mastering macOS keyboard for better efficiency

In the past few years, I have seen a rise in MacBook Pro usage in tech companies, including in Jakarta. Although pricy, MBPs are one of the primary go-to machines for tech folks around to world. The well-known butterfly-switch issues since 2016 don’t seem to prevent people from buying MBPs, which thankfully fixed for good in the recent new 16″ model. In my opinion, one of the main reasons for this rise is the productivity value it brings along with the macOS.

In the software engineering field, macOS has many things to love. It’s UNIX-based, which is almost similar to the Linux environment used for most server-side services. For mobile app engineers like me, macOS allows us to develop applications for both iOS and Android. Not to mention the OS integration with the trackpads, which unrivaled in the laptop realm – its buttery-smooth experience convinced several designer friends of mine to work mostly using them. Nevertheless, I found that the senior engineers I worked with use their keyboard more than their trackpads. They seemed to be able to do things way faster than others due to mastering their keyboards.

Throughout the years, I’ve tried to reduce my trackpad usage and use more keyboard for work, which I find to be efficient. I wrote this based on my experience, so you might find this post to be opinionated. Still, I hope you could draw some benefits that could increase your work efficiency.

1. Use macOS’ Spotlight

Most Indonesians (including me) grew up using a Windows machine as our daily driver. So on our first time we got our hands on a Mac, we’ll be looking for the “Programs” folder using our mouse and click the application icon to run them.

Windows XP’s Start Menu. I grew up seeing this menu a lot of times. Image taken from OpenDNS.

While we can run applications the same way in macOS, there’s a quicker way to do it: using macOS’ Spotlight. All we need to do is press the Command + Space key, type the application name, and then press the Return key (or Enter in other keyboard layouts).

Screen Shot 2020-01-06 at 20.27.33
A sample screenshot on how to open applications using Spotlight in macOS.

On the screenshot above, I only typed “xc” in the Spotlight, and it shows the most-used application with a matching prefix: Xcode. All I need to do next is pressing the Return key to open the Xcode.

Besides opening applications, macOS’ Spotlight also provides a lot of nifty features, e.g.:

  1. Opening a file based on filename,
  2. Calculating a simple conversion, e.g., “1000 USD to IDR” or “70 F to C”, or
  3. Searching a word definition in the thesaurus or dictionary, e.g., “hitherto.”

2. Use a third-party window manager

Coming from the Windows environment, I missed the Windows Aero’s Windows + Arrow keys combination to tidy up my application windows (pun intended). When I started using OSX Maverick, my friend suggested me to use SizeUp. The site page says that its the “missing window manager” for macOS, and it’s not an exaggeration.

With a simple combo of Control + Option + Command + Arrow keys, you could arrange your windows with ease! I find this approach is way more efficient than macOS Split View feature. For multi-monitor users, SizeUp could move the currently active window to another monitor using the Control + Option + Left or Right arrow keys. What’s not to love?

You can use SizeUp for free due to its unlimited demo. Still, it shows a pop-up periodically until you bought their license. If you wanted a free open source alternative, check out Spectacle. Be warned, though; the source code is not maintained anymore.

Continue reading “Commit #9: Mastering macOS keyboard for better efficiency”

Commit #8: An introvert’s take on mentoring engineers

Do you prefer reading books or listening to music over partying for your “rest time”? Or planning deliberately instead of taking spontaneous ideas when speaking in the front of a crowd? Are you feeling drained after interacting with a lot of new acquaintances, wanting to retreat? If your answer is yes, there’s a big chance you’re an introvert (or ambivert) like me.

Us introverts have to rest after a certain amount of social interaction. It doesn’t mean that we hate people… our brain has different wirings on how to recharge ourselves. Due to my introversion, I tend to evade unnecessary social interactions since young, which inhibited my social skills. Growing up, I realized their importance and ended up analyzing my extroverted friends to catch up. (Yeah, that sounds nerdy, I know.)

I learned that social interaction takes different forms and contexts. In the professional setup, these interactions come in various kinds – discussing in a meeting, writing technical documentation, listening to a person, and giving proper response. Out of all of them, I took an interest in a particular interaction: mentoring. And I want to share what I learned about it as an introvert in this post.

Why mentoring?

As humans, I believe most of us learn from experiences. A mistake from the past, for example, provides reasons and steps to prevent a similar outcome in the future. Thankfully, we don’t always need to learn these lessons from firsthand experience. Reading one’s experience through books is a great example. Another alternative for reading is (surprise, surprise) mentoring!

A proper mentoring could significantly accelerate the mentee’s growth. In the process, a mentor tailors lessons based on the mentee’s needs. In addition to the lessons, they also provide a living example for the mentees – an advantage which reading lacks. In my opinion, nothing increases confidence more than someone who models on how to do something properly.

In addition to the mentee’s growth, the mentoring process forces the mentor to grow, too. Besides the required accountability from “practicing what you preach,” the mentees could also drive the mentors out of their comfort zones through their questions. I experienced these on my career growth, and I’m thankful for it.

From a business perspective, mentoring provides a long-term value. On The Effective Engineer, Edmond Lau states that investing in your team’s growth is one of many high-leverage activities, which will multiply the given effort as a result. Mentoring is one of them since it will help the mentees to grow and take part in the mentor’s responsibilities. Following the mentees’ growth, the mentors could delegate their tasks and tackle more challenging responsibilities.

Last but not least, I have seen the impact on both being a mentee and a mentor to career and personal growth. My personal growth is the main reason why an introvert like me bother writing a post about mentoring. It also helped me to push my comfort zone a little bit wider every time I get demotivated as a mentor.

Make a one-on-one routine

As an introvert, I reluctantly start social interaction with others. My comfort zone as a junior engineer was working on my code while listening to music or reading through technical blogs. Sure, I could speak in front of the public or explaining in-depth technical details in a one-on-one setting, but those events require enough preparation and happen infrequently. This comfort zone was blasted when I got promoted and requested by my manager to mentor junior engineers two years ago.

Based on my mentoring experience in college, I know that I need to ensure my mentee’s growth by checking on them periodically. The context is slightly different, though – I still need to deliver my day-to-day job! Left alone, I might ignore my mentees due to my introversion and use my workload as an excuse.

To battle my comfort zone, I decided to schedule my mentoring sessions. I sent a periodical schedule for each mentee in my work calendar. Having it on the calendar helps me to plan my day, leaving me with no room for an excuse. It also helps to remind the mentees to allocate time for the sessions, too! On top of that, it prevents others from disturbing us during the allotted time.

When having a one-on-one session, it’s important to remember that your mentee is human. Your mentee has a personal life, and it affects their performance in the workplace. This fact has driven me to ask for their well-being at the start of a session. Is there something that they’re concerned about outside of work? Or perhaps a great experience from last weekend? The answer could be anything – A typical “everything’s fine,” a passionately-told story, or an in-depth discussion. Your mentee might be reluctant to open up on the first few sessions, which is normal. Try to open up to them first. Share your experience or thoughts when they share theirs, and deliver it in a positive language. Offer help when possible.

After discussing their concerns outside of work, ask for the work-related ones. Should they raise technical questions, try your best to ask their thought process first before giving the answers. If it’s outside of your forte, refer to others who might be able to help them. Don’t hesitate to ask them to explain the solution when they solved it – and appreciate them when you learned something new!

There are times when your mentee’s concerns related to the workplace. Listen to them well, since you are their go-to person to raise their concerns to the management. If you’re not senior enough to offer a helping hand,  you could raise it to your higher-ups, too. It’s also a good chance for you to impart cultural company values or lessons – e.g., how to tackle an over-promised feature.

Last but not least, ask for their technical growth. What have they learned since the previous session? You could improve this by assigning a specific material or book to be discussed, which is even better if it applies to their day-to-day work. For me, I always assign new hires to read the Clean Code book for starters and discuss each chapter in each session.

Remember to take notes on every session, based on the date. Writing down their concerns and learned lessons will help you to track their growth. It will also help you to follow them up on future sessions. Those notes could also serve as evidence to the management during their periodical performance review.

Continue reading “Commit #8: An introvert’s take on mentoring engineers”

Commit #7: Useful practices for leading an Agile team

2016 has passed, and people had different opinion on it. The internet seemed to think that 2016 is a complete disaster, though. Political turmoils, wars, death of famous figures, and our personal miseries propagated through social medias and memes. This meme depicts the thought pretty well:

I got my share of miseries for 2016, but the old hymn reminded me to count my blessings. I realised that through the whole year, I learned important lessons from my workplace.  One of the most valuable lesson I had was more chances to lead iOS team in projects.

Moving from a single contributor to a team leader wasn’t easy. I need to deliver stories while facilitate my teammates to deliver theirs. Along with other leadership principles that commonly known, I found out that these practices helped me on leading my team, which were establish shared grounds, foster ownership, and schedule technical retrospectives.

Establish shared grounds

Have you ever found a codebase that has different writing style on every file? Or worse, on every line? Something like this:

func aSampleFunction() {
let something = Something()
if something.isFree {
print("hey this is free!")
} else { print("and this is not") }
if (something.isStrange) print("this is strange")
else { print("who am I to decide") }
if something.isBroken
print("we need to fix this")
print("this is good as new!")
print("these brackets made me crazy!")

If you’ve been writing code for a while, you’ll know that this practice is bad. Inconsistent writing style allows us to miss details when reading the code. This make bug-fixing become harder. Even worse, it could cause a bug when somebody adding another code on the top of it. Personally, this kind of code grinds my gears, because I prefer writing and reading clean code.

I’m not making things up, since I have found such code on client’s handed over projects (sigh). The number of inconsistencies usually rises along with the project’s age. You might have found some in forms of snake_cases in a CamelCase-based language, or mixed architectural patterns between MVC, MVVM, or VIPER… or Massive View Controllers for iOS projects ūüėĒ. Along the way, I realized that none of these projects has standards set for them.

In my humble opinion, every new project should have a standard set before the development. If you’re using Git as your source control, you could put the list of standards in a file. Git-based hosting sites (e.g. GitHub, BitBucket) normally show the README content on the project’s home page, allowing visitors (and new contributors) to read the standards before jumping to the code. Here’s a list of standards that I have set in projects I have led:

  • Architectural pattern. Should we use MVC, MVVM, or VIPER? If there’s a modification to the pattern, kindly specify it in the README file. For example, our iOS team usually uses MVVM along with Krzysztof Zablocki’s FlowControllers.
  • Project structure. How should we structure the folders? Which folder should we choose to store a certain type of class? Our iOS team usually laid out the folders based on business domain first, then type as subdomain (e.g. Views, ViewControllers).
  • Style guide. Referring to the sample code above, each person has different coding style. If not specified, a project could end up with inconsistent writing style or wasted time on useless debates. I recommend every project to have a writing style guide to keep consistency and increase readability for maintainers. If you’re using Swift, you could use GitHub’s Swift style guide. Ray Wenderlich’s style guide is a good choice, too.
  • Contributing guide. What’s the branching strategy for this project? How should contributors add new features or bug fixes to the codebase? If any, how much code coverage should be achieved? Who should review each pull requests?
  • Dependency manager.  What are the preferred dependency manager to use for the project? How to install the dependencies? What are the rules when someone want to add a new one?

This practice seems pedantic and unnecessary, but it has helped our team to onboard new contributors with minimum supervision. It also helped us to have a “single source of truth”, which frequently referenced when we’re reminding each other. I have found that every minute shed in making this standard has paid off multiple times.

Continue reading “Commit #7: Useful practices for leading an Agile team”

Commit #6: Unwrapping Swift optionals

Update 12 Oct ’16:¬†I’ve updated the code in this post and the Xcode Playground blog post version¬†to Swift 3! Thank you for the wait¬†ūüėĀ

As an iOS developer, handling empty value cases in Objective-C is never easy. Let’s suppose we’re making a function that return NSString¬†instance out of a NSDictionary:

/// Will return @p NSString representation of user's token from passed @p payload, or @p nil if there's no user token in it.
– (NSString *)userTokenFromJSON:(NSDictionary *)json
return json["user_token"];

view raw
hosted with ❤ by GitHub

Everything seems fine, isn’t it? The¬†method’s logic is pretty clear – it returns the value in user_token¬†key of the JSON. If the key exists, it will return the string. If not, it will return a nil value… dead simple, right?


I left out a sanity check there, but ¬†let’s continue our example for now.

Suppose that the returned string will be encrypted and stored by C++ library. And for that, we need to cast our NSString to C string:

– (void)storeUserToken:(NSString *)userToken
if (nil == userToken) {
const char * rawString = [userToken UTF8String];
// Further code that uses rawString here…

Where’s the problem, Do? Everything looks fine…

Right. The method above looks good – it stopped the process early if passed userToken¬†is nil. Both of them will work correctly, until¬†somebody from the server side single-handedly pass null value in response¬†JSON’s user_token key, instead of omitting it.

Let’s run through the code once again. If the passed JSON is made from NSJSONSerialization process, the user_token key will store a¬†NSNull¬† instance. Thus, the result from userTokenFromJSON:¬†will be a NSNull instead of a nil or NSString – which will allow it to pass through storeUserToken:‘s early sanity check code (since it’s not a nil), and¬†break the whole app, since NSNull doesn’t have UTF8String method.

Let’s hope this case will never happen in production servers. And yes – I’m looking at you, cowboys.

Due to this issue, nil-checking alone in Objective-C isn’t sufficient. We also need to ensure¬†whether an instance is the right class using isKindOfClass:¬†method. It doesn’t always work well either – for example, if the server on the example above returns a number for user_token¬†value,¬†there’s a chance that it’ll read as _NSCFString¬†(Apple’s private API)¬†instead of a NSNumber.

That’s why after a few month working with Swift, ¬†I grew appreciating the Swift Team’s decision to include¬†Optionals. I believe they made¬†this as an answer to Objective-C’s tedious¬†sanity check. The documentation clearly says that:

You use optionals in situations where a value may be absent. An optional says:

  • There¬†is¬†a value, and it equals¬†x


  • There¬†isn‚Äôt¬†a value at all.

If I declare a variable to be a String?¬†(read: String Optional), it would either be a String value¬†or a nil. Not a NSNull,¬†not other class type, and not another Apple’s private API. So, userTokenFromJSON:¬†above could be rewritten in Swift into this:

/// Returns `String` optional representation of user's token from passed `json`.
func getUserToken(json: [String: AnyObject]) -> String? {
return json["user_token"] as? String

And yes, this method will an Optional – either ¬†String¬†or a nil.¬†ūüôā But the process isn’t ended here – we need to take the available String¬†value out of the Optional. The term is usually called as¬†unwrapping in Swift development –¬†and there are several ways to do it!

Wait, it seems I¬†had¬†enough rant above… this post started to feel edgy. Let’s change the mood, shall we?

In this post, I’ll list the ways for unwrapping Swift’s Optionals that I have found so far. For the sake of the post,¬†let’s assume we got a new function that needs a String input and an Optional variable:

func createGreetings(sailorName: String) -> String {
return "ūüĎģ Ahoy, \(sailorName)! Welcome to S.S. Salty Sailor, arrr!"
var name: String?

view raw
hosted with ❤ by GitHub

Now, we need to unwrap the name (since it’s a String optional) to pass it to the createGreetings(sailorName:). There are several ways to do this:

Continue reading “Commit #6: Unwrapping Swift optionals”

Commit #5: On choosing learning materials

For us who work on the field of software engineering (and its neighbours), it is no secret that we constantly learn new things. Driven either by need¬†or curiosity, it seems like learning is a never ending quest for us. Some of them have direct impact to our craft, like how¬†using Xcode’s debugger¬†could save us from headaches,¬†or how¬†side menu¬†reduces user engagement¬†with your app. Some of them are just for fun – like how¬†TrumpScript¬†is making Python great again (duh), or how a build engineer automates everything¬†using bash scripts, ranging from scanning e-mails to ordering the coffee machine (!).

As a software engineering company, Ice House has a diverse learning scene. We have two main diets in our learning materials:

  1. Knowledge in our main craft, e.g. iOS or Android. To deliver the best quality, we always strive to know better about our own backyard.
  2. Specific knowledge which needed in client¬†project’s domain, ¬†such as geolocation or image processing. Sometimes, our client requests more than a simple mobile app to compete with current market.

Outside of that, each of us has our own preferences. Some of us¬†love to venture outside of our comfort zone,¬†such as playing with Arduinos, explore new programming languages / concepts, or tinkering with new game development tools. As for me, I found myself learning much more general topics, such as¬†clean code, test-driven development,¬†or¬†design patterns. Sometimes I’m afraid a new platform-specific knowledge would quickly obsolete – especially on today’s tech pace.

Last week, I joined a design-and-define workshop for a new client.¬†I had a chat with our software architect during¬†a session’s coffee break. He has more than ten years of experience¬†in software engineering, and had several years working as Senior Director of Engineering for Citrix’ mobile platforms. I always knew that he has a vast knowledge about a lot of things, but I witnessed it myself up close on the workshop sessions. Wondering if he’s still learning new things these days, I asked him straight away:

M (Me): So, what are you learning about these days? Got anything new?

H (Him): Hmm… nothing much. I currently playing around Kotlin and Swift.

M: Kotlin?

H: Yeah. You know, the new language from JetBrains – some people build Android app on top of it.

M: Whoa. Do you also planning to build Android app with that? Or perhaps using Swift for backend?

H: Maybe¬†– as a software engineer, it’s always a good thing to keep up with today’s technologies. At least, I’ll learn new paradigms that might be useful later.

I found myself agreeing with his last statement, but I also start¬†wondering how he picked his learning plan. He’s an architect, and it’s his job to keep being updated with general software growth. Why did he chose Kotlin and Swift? Why not Haskell, Node, or others? Curious, I continued our discussion with this:

How do you choose what to learn next?

Continue reading “Commit #5: On choosing learning materials”

Commit #4 : My top seven clean code practices

Hi there, fellow readers! It’s been more than a month from¬†my latest commit, where I promised this post will be published a week after ūüėÖ Sorry for the delay! I got my hands full for a month ūüėď

As I said before, the Clean Code book got tons of useful practices. In this post, I want to show you how I applied a few¬†of them in my code – which mostly¬†is¬†Objective-C, hence the examples on this post ūüėČ I believe I don’t always get it right either, so I’d love to hear from you if I got something wrong on how I applied it! ūüėĀ

So,¬†here’s the top seven clean code practices I mostly use! ūüėÜ

Continue reading “Commit #4 : My top seven clean code practices”

Commit #3 : Clean code matters

*dusting blog*


Hi there! It’s been months¬†since my latest post commit here, work life sure can be tight ūüėÖ ¬†After two tutorials, let’s try some different type of commit, shall we? This time, I want to share about a book that changed the way how I code.

It was on my early days in Ice House. Some of our higher-ups just came back¬†from US and brought technical books for us. I was reading a copy of ¬†The Pragmatic Programmer¬†at that time, so I didn’t really looked at the new books.¬†After a few days,¬†Ridhwan¬†handed a copy of Clean Code to me, and said this:

Check this book out, do. My code structure changed a lot, even only by reading a few chapter of it.

I took it with a so-so feeling. I was reading the Pragmatic Programmer,¬†and that book made me feel worthless. It was full of best practices that I haven’t done (yet), so full of it that I was confused where should I begin with. I was unsure whether I can take something practical out of Clean Code. I was afraid (duh)¬†that it will make me feel worthless again. Yet,¬†I ended up reading it. It was recommended by the prodigy*, so… why not?

I read the introduction (it suggests amazing measurement for code quality) and the first chapter, and BAM Рthese paragraphs pops out:

Continue reading “Commit #3 : Clean code matters”

Commit #2 : Export your *.xcarchive to *.ipa via terminal!

December last year, several Ice House clients asked for Christmas update on their app.¬†There’s a strange case that occurred when our team tried to send old projects to the iTunesConnect using Xcode 6’s Organizer, just like this image :

Screen Shot 2015-01-09 at 17.12.22

Our supervisor, Didiet, said this issue might be caused¬†by¬†the project file. The project was built on¬†Xcode 5.1 and we’re¬†trying ¬†to publish it from Xcode 6. Since we don’t have much time left, we ended up using xcodebuild‘s exportArchive¬†command from terminal to export the *.xcarchive from Organizer to *.ipa :

Continue reading “Commit #2 : Export your *.xcarchive to *.ipa via terminal!”

Commit #1 : Bash up your workspace!

It’s all started when I was assigned to develop¬†a Rails web app with Haris¬†as a team. He worked on the Rails side, while I’m on the HTML / CSS.¬†It was my first time using Rails, and I barely have any experience on web development. Haris told me that there are several commands that should be executed to enable developing the web locally :

  • mysql.server start
  • rvm gemset use iceberg,
  • bundle install,
  • bundle exec rails s, and
  • bundle exec foreman start for running Redis server (on other terminal instance)

At that time, I typed all of those commands on my terminal¬†each time I start working on the app, until I’ve made an embarrassing mistake – twice.Continue reading “Commit #1 : Bash up your workspace!”

Commit #0 : Hello, world!

Hi! My name’s Edo, and this is the first time I’m having a blog dedicated on a domain named on my own nickname (duh).

This blog is intended to be a personal journal of mine on learning to be a better mobile developer. I’ll¬†try to post things that I’ve learned along the way (at least, most of it *fingers crossed*).

I’m hoping that you found this blog interesting! ūüôā

P. S. : I was thinking to set my the title as “Good morrow, fellow subjects of the Crown“. On the second thought, I realised that I’m not that fond of British nor PHP as my main language (human and programming, respectively).