Google still knows how to really swag| kau.sh
AI is transforming our tools, our writing, and — apparently now — our sense of typographic originality. But there are two quirks of my writing that now get me side-eye from friends: em and en dashes predominant lowercasing I know, i know. nobody likes the guy who says he liked the band before they got famous. but here we are. I was lowercasing and em-en dashing before AI and i’d like to claim this back please. my friends roll their eyes when i try. even the polite ones. so, since i can...| kau.sh
I recently found myself in a deep state of flow while coding — the kind where time melts away and you gain real clarity about the software you’re building. The difference this time: I was using Claude Code primarily. If my recent posts are any indication, I’ve been experimenting a lot with AI coding — not just with toy side projects, but high-stakes production code for my day job. I have a flow that I think works pretty well. I’m documenting it here as a way to hone my own process a...| kau.sh
Introducing “shorts” for Henry (my Hugo blog engine/theme). Often, I find myself wanting to post a quick thought or note without the ceremony of a full-blown “blog post”. That’s usually when I’d post to Bluesky, X, Threads, or Mastodon. But as I’ve said before, I prefer investing in a feed I control. With Henry, I can effortlessly post a quick thought, and share it from a feed I own.| Kaushik Gopal's Website
A developer podcast host recently said they only use AI for autocomplete. This shocked me. That’s two generations behind today’s state of the art. This is how the field is evolving: AI Programming Paradigms at a Glance Super autocomplete: AI predicts code, not just keywords. Conversational Coding: Chat with your IDE, direct the AI, iterate together. Agentic Coding: AI acts independently - runs commands, checks work, iterates. Simul Agentic? : Multiple sub-agents, parallel workflows, worki...| Kaushik Gopal's Website
Context is king. Getting useful results from your AI assistant often hinges on providing the right instructions. Yet most developers take this step casually, then wonder why their AI outputs are mediocre. You provide context through two channels: Your immediate prompt — the main prompt you type in to the chat1 Master instructions — persistent rules that shape every interaction (this post’s focus) If you use different tools, you’ll quickly discover the currentlandscape for how to provi...| Kaushik Gopal's Website
I just read a good piece by the Nilenso crew on AI-assisted coding for teams that can’t get away with vibes. Blog post title aside, it helped me synthesize my own thoughts better on a question that keeps coming up: will AI replace all software engineers?". Not only won’t it replace us, it’ll make the best engineers even more valuable. Here’s why. AI amplifies what you already have AI is a multiplier. To make AI good, get good yourself. AI is a multiplier. If you are a small coefficien...| Kaushik Gopal's Website
If you’re obsessed with productivity hacks, you’ve probably heard of Karabiner – the ultimate tool for keyboard customization on macOS. But maintaining Karabiner’s config is a pain. In this post I’ll show you a simpler, Kotlin-powered way to wrangle your Karabiner setup, so you don’t have to wrestle with massive, unwieldy JSON. On Karabiner Here’s the gist: Karabiner lets you intercept any keystroke and remap it to… well, pretty much anything. Want to turn Caps Lock into a Hyp...| Kaushik Gopal's Website
I use the Pixel 9 Pro as my daily driver and love it. But one notable feature I’ve always missed from the Apple ecosystem is AirDrop. I typically have WhatsApp for Mac open and dump things there for quick access between devices. Clunky, but it worked. Until I realized Tailscale —a VPN1 that I love and use— has a feature called Taildrop. The name suggests it’s meant as an AirDrop competitor, and I’ve been super happy with it. I can now send images uncompressed2 to any of my devices. ...| Kaushik Gopal's Website
When you’ve been doing a podcast for so long and it’s a pure labor of love –time and again– you start to ask yourself: why am I doing this again? This is a note for myself and others, who sometimes worry about the podcast. Positive listener feedback Probably, the single most influential reason for doing it is those 2 or 3 notes or messages I get over the year when someone says that the podcast helped change the course of their life as a developer. I’ll be honest. I didn’t think th...| Kaushik Gopal's Website
On a ✈️ back home, I decided to add Dark mode support to Henry. Having recently upgraded to Tailwind CSS 4.0, this was a piece of cake to do. I leverage the widely supported CSS @media prefers-color-scheme feature and Tailwind’s native dark-mode support. The implementation only required a few changes: 1. update main theme.css In my main theme.css file where I declare the existing colors, I add the CSS @media selector for the “dark” variable indicator. @theme { /* henry background */...| Kaushik Gopal's Website
Update is now out The latest firmware update is out now. Update your Mac (iPhone or iPad) to the latest version & connect your Airpods Max should update its firmware. Apple just announced ultra-low latency support for the USB-C AirPods Max, and it changes everything for podcasters. Yes, they still cost an absurd $500. But now they’re worth their weight in starlight1 gold. Courtesy: Apple.com Why AirPods Max Are Now Perfect for Podcasting Here’s the game-changer: you can now “monitor” ...| Kaushik Gopal's Website
Many software engineers (myself included, not long ago) have been anxious about AI replacing our jobs. It’s a natural concern. But I’ve been diving deep into using AI for software engineering. I’ve had a realization: We should stop worrying about job losses. Start seeing AI as a tool to make us more valuable. The key? Use AI for learning, not just code generation. Relying solely on AI for code generation is the trap. The truly valuable skill is judgment1. The judgment to decide what to ...| Kaushik Gopal's Website
I’ve been following the awesome Gina Trapani for quite some time1. She recently built a tool to track her life in weeks (inspired by Tim Urban of Wait But Why fame’s own article). As I get close to another complete revolution around the sun, the only thought that went through my mind reading this: Terrifyingly Inspiring. --- Lifehacker ❤️. It shaped my early internet years. ↩︎| Kaushik Gopal's Website
I use Obsidian for tracking my weekly tasks1. One thing I like to do, is mark tasks as “canceled”, “rescheduled”, “in progress”, etc. in case I move them between weeks. These tasks should visually stand out from the rest. Custom themes like Obsidian Minimal provide this as an option. There’s also plugins that do this. But I like to keep my Obsidian setup lean and only wanted this feature without other cruft. CSS to the rescue again! The linked forum post had the starting css sni...| Kaushik Gopal's Website
In Vinay’s latest newsletter, he asks a few of us #AndroidDev to predict what the future of Android development is going to look like. Yours truly had this as one of the predictions: AI everything 🙄 … On the product side, we’ll see more on-device AI, with smaller models like Gemini Flash/o3-mini running locally to provide operator-like intelligence directly on phones and this will probably be what most folks are geared towards doing for mobile development. Looking at this Youtube vid...| Kaushik Gopal's Website
One of the challenges with note taking apps on mobile is the limited font selection. While desktops let you install custom fonts system-wide, mobile platforms are much more restrictive. However, there’s an elegant solution for Obsidian given it’s an electron app. Obsidian allows you to inject a CSS snippet to tweak the appearnace of the app. CSS allows you to embed base64 encoded fonts directly in them for styling text 💡. I figured let’s try this and see if it works on mobile. Works ...| Kaushik Gopal's Website
Twitter’s change in ownership triggered a cascade of events birthing various social media clones. It’s been tricky to decide which network to invest time and energy in. I’m not an influencer, but I’d be kidding myself if I thought having a presence on social media wasn’t important. The recent TikTok drama has given me clarity on one extremely important principle that all creators should have learned by now: Invest in channels you control. Invest in channels you control I recently mo...| Kaushik Gopal's Website
I use a pixel as my primary android phone. But as a mobile developer, I also keep an iPhone handy for those times I need to test how an app works on iOS (especially if it’s not available on Android1). But my iPhone doesn’t sit in a drawer unused. It doubles up as my webcam when not being used as a phone. This is possible because I use macOS for my primary desktop needs, and this wonderful feature it enables called “Continuity Camera”. I’ve removed a webcam from my setup thanks to th...| Kaushik Gopal's Website
I’ve been using this font for a while as my primary programming font and referenced it in one of my newsletters. Thought i’ll share this more prominently. This website now uses Commit Mono for code. I customized a few of the characters: There are better ways to design than putting a big effort into making something look special. Special is generally less useful than normal, and less rewarding in the long term. Special things demand attention for the wrong reasons, interrupting potentially...| Kaushik Gopal's Website
series This is part of a series of posts on Coroutine Testing: Picking the right Dispatcher Never ending tests & backgroundscope Controlling time ← Helpful @Junit TestRule extension (coming soon) Full USF example for Android (coming soon) My journey with coroutine testing started with this “simple” requirement — to control virtual time in concurrent logic. From my previous post: … If you don’t use a StandardTestDispatcher explicitly, then operators like runCurrent, advanceTimeBy e...| Kaushik Gopal's Website
My good friend Mustafa has some sage advice for Sonos on the recent rewrite fiasco. Fix all issues and test the new app very thoroughly with external beta testers before relaunching. Have the best crisis leader at the company take over. Find all ICs who have been raising the alarm and give them authority to move fast. Remove anything that gets in the way - … Create a single source of truth - all issues, feedback and bugs should flow into a single place. Have a small team (<=3) triage and pr...| Kaushik Gopal's Website
series This is part of a series of posts on Coroutine Testing: Picking the right Dispatcher Never ending tests & backgroundscope ← Controlling time Helpful @Junit TestRule extension (coming soon) Full USF example for Android (coming soon) If you’ve spent some time testing Coroutines this exception should look familiar: After waiting for 1m, the test coroutine is not completing, there were active child jobs This tends to happen when you have a coroutine job in your test, that fails to comp...| Kaushik Gopal's Website
When the #androiddevs transitioned from Rx to coroutines the topic of testing didn’t get as much attention in this new world of concurrency. It didn’t help that there was a seismic change in Kotlin’s testing apis with 1.6.0. A whole bunch of online resources and tutorials are now defunct courtesy this change1. My journey in the matter started because I simply couldn’t understand why test apis like advanceTimeBy wouldn’t work reliably for me. The name made sense… but my time wasn...| Kaushik Gopal's Website
series This is part of a series of posts on Coroutine Testing: Picking the right Dispatcher ← Never ending tests & backgroundscope Controlling time Helpful @Junit TestRule extension (coming soon) Full USF example for Android (coming soon) Most of the problems and flakiness around coroutine testing stem from running them on different Dispatchers. This is because the choice of Dispatcher can significantly impact the behavior of coroutines. This was also the most confusing1 part for me startin...| Kaushik Gopal's Website
Before diving into a new feature, I always tell my team to scout the parts of the codebase that will need to change. As we explore, refactor for clarity. These cleanup changes get their own pull request1 (PR) before we touch the new feature. This PR shouldn’t change functionality, just tidy up the existing code. This gives us a few big wins: Better estimates: We can estimate the feature’s timeline more accurately now that we have a much better sense of what’s about to change. Smoother r...| Kaushik Gopal's Website
Fyi Updated for Tailwind CSS V4 I veer away from CSS frameworks like Bootstrap because they result in sterilized designs. On a recent side project, I gave Tailwind CSS a try and am now a believer. “Rapidly build modern websites without ever leaving your HTML” makes a lot of sense to me. Case in point: I rebuilt my Hugo theme, Henry, with Tailwind in three days1. I quite like how it’s turned out. Let me show you how to add it to a Hugo theme. This has become even simpler with Tailwind CS...| Kaushik Gopal's Website
If Android developers don’t setup the JDK correctly, you’ll be greeted with nasty errors like this: Check your module classpath error Cannot access 'java.lang.constant.Constable' which is a supertype of 'java.lang.Class'. Check your module classpath for missing or conflicting dependencies Your app might compile fine but the IDE will keep surfacing pesky errors. This is because Android developers have a variety of ways to setup the JDK for your development environment. Too many. On episode...| Kaushik Gopal's Website
Welcome to the third installment of my newsletter. Your support as always means everything to me. Let’s dive in. What I’m watching, listening, reading [video] You’re Not Forgetful: My System for Memorizing Everything Most people think they have a terrible memory. I know I did. This video by a YouTuber doctor challenged me to rethink that. I haven’t noticed a change in my memory’s capacity, but I’ve learned how to remember more. [video] Apple TV+ Masters of the Air Exceptionally sh...| Kaushik Gopal's Website
Ever tried using the option key (⌥) with another character as a keyboard shortcut in a macOS app? For example, in Obsidian I use ⌥ r to replace templates in the active file; or ⌥ a to archive completed tasks for the day. Using the default English > U.S. keyboard (or ABC) types special characters in your app like å or ® vs executing your app shortcuts. It’s frustrating. If you’re heavy keyboard shortcut or a programmer wanting to use more keyboard shortcuts in your IDE like me, you...| Kaushik Gopal's Website
Welcome to the second installment of my newsletter. Your support means the world to me. I’ve been told the key to building an audience is consistency. I’m committing to this idea by releasing my letter on the first day of each month. This way, you’ll always know when to look out for a new letter. Let’s dive in. What I’m watching, listening, reading [podcast] What Now? – Trevor Noah’s standup is good but he’s an even better interview host. His “Between the Scenes”segments a...| Kaushik Gopal's Website
I wrote a blog post about git-number and how useful it was for my command line git usage. In an on-going effort to simplify my lifestyle & setup, I replaced git-number with a few git aliases. I’ll explain how I recreated the functionality in this blog post. Why replace it? Looking at git-number’s source I realize it is written in Perl. I’m not here to cast judgement on another programming language but reading the code, it felt like overkill for my use cases. It also meant I could elimin...| Kaushik Gopal's Website
Tip As penance for that click baity title, I won’t bury the lede. These are the tools you need: Gmail filters Simpl.fyi plugin Read on for specifics and examples. I’ve tested several email apps—Mimestream, Superhuman, and Hey—but none quite stuck. They either pushed me too far from Gmail’s setup or simply didn’t resonate with me. The closest match was Inbox, until Google notoriously put the kibosh on that. Imagine my surprise then, when I discovered Michael Legett, (Inbox co-found...| Kaushik Gopal's Website
Welcome to my newsletter! Why start a newsletter when I have a blog? I love writing and I want to write more. But I want a more casual format, where I can share without the burden of permanence or meticulousness that a “blog post” demands. While I continue to use social media, like others I remain skeptical of its future as a reliable destination for this sort of writing. What to expect Think of this truly, as letters from me to you. I intend to share quick tips and tricks; helpful softwa...| Kaushik Gopal's Website
OpenType fonts have font features or variants that you can use to represent certain characters differently. For example, my beloved IBM Plex Mono1 has quite a few alternative glyphs to pick from: I prefer the single story “g” and slashed “0” characters for clarity. But you’ll find no obvious way to turn these version of the characters on permanently. After searching and trying quite a few ways to do this, I found an approach that works pretty well. This blog post will explain how yo...| Kaushik Gopal's Website
Shopify CEO Tobi Lütke in a tweet last year mentioned why he uses the Rectangle app even through Raycast has some of these options already. Rectangle allows you to “toggle” the window to different positions. I was inspired by this and wanted to be able to do the same. But in keeping with my theme to Simplify, I didn’t want to add a new tool to my arsenal. Keyboard Maestro1 to the rescue! This set of macros allow you to toggle between a few states: Toggle to the left ½ ¼ ⅔ of the sc...| Kaushik Gopal's Website
One of the gifts we got from Kotlin 1.3.70 was the ability to effortlessly run a kscript (Kotlin script) from the command line. All you need to do is add the suffix .main.kts. Seriously, this is all you need to do: brew install kotlin echo '#!/usr/bin/env kotlin' > hello-world.main.kts chmod +x hello.main.kts ./hello.main.kts # 💥 With this 0 friction setup, there’s little reason for me to ever write a bash script again. I get to write my script in Kotlin — a modern & beautiful language...| Kaushik Gopal's Website
One of my resolutions this year was to start picking up the Tabla again1 courtesy a not so gentle nudge from my supportive partner. This has obviously led me to scouring Youtube for videos of the great maestros. Ustad Zakir Hussain is one of them. Here’s a few videos from my collection with some context explaining why he’s a gift to the world of music. What is the Tabla? If you want to get a quick peek at this supremely delicate Indian percussion instrument here’s a starter video. Zakir...| Kaushik Gopal's Website
I’m always trying out new tools to make my life easier. In a cruel twist of irony however, I’ve found myself customizing and maintaining multiple tools leading to unnecessary complexity and a hit in productivity. So this year, I’ve made a resolution to simplify and eliminate redundant tools. Nothing is safe from the chopping block! Here are some of the major transitions I’ve made or plan to make, and I’ll be sharing more about each of them in upcoming posts. Things 3 → Obsidian No...| Kaushik Gopal's Website
Every time I create a new post in this blog I like to toot or tweet about it. Instead of manually doing this, I have my Mac Mini run a little shell script on a cron job, that does this automatically for me. You can download the source for this script over at github. The way it works is pretty simple: Download my latest blog feed as a json file. Check for any new blog posts. Compares with a local CSV file that records previous toots. Posts new toots to Mastodon1 Running the script is trivially...| Kaushik Gopal's Website
Owning your content and where you put it is crucial in the online world. The first step to establishing your corner on the internet is to choose a domain name1. After obtaining a domain name, many people only set up a website. However, I recommend taking the next step of creating subdomain redirects for your social media handles. By Cloudinary, CC BY-SA 4.0 For example, when mastodon.social suffered a DDoS attack, I moved to hachyderm.io2, but the mastodon link I hand out to folks remained un...| Kaushik Gopal's Website
When I travel on airplanes, I prefer to download content onto my 14" Macbook1 so I can watch it offline during the flight. When my wife travels with me, we like catching up on some of the shows that we like to watch together. But we both have our own pair of Airpods that we’d like to use to listen to the audio together. In the wired headphones days, I’d carry a headphone splitter that we’d plug both of our wired headphones into. Courtesy: Wikimedia This blog post provides instructions f...| Kaushik Gopal's Website
Looking back at 2022 🎉 Bought a new home 🤯 2022-02-22 Joined Caper as Head of Android 🙈 Got Covid Put productivity system in place Setup Mac Mini server, Tailscale & Homebridge Introduced Henry 2.0 & major updates to the blog Moved domain name over to kau.sh 2022 Goals ✅ Moved from goofy jkl.gg → kau.sh Make home smarter ✅ Automated blind shades ✅ Clean network topology (LAN in all rooms) Smart Alarm Video Camera feed inside ✅ Unify all of existing systems with Homebridge R...| Kaushik Gopal's Website
A few Kotlin constructs have been introduced into the language over time. I wrote this post as a personal/public service advisory to remind us of their significance. Would love to credit img owner 1. fun interface (SAM)1.1. (vs) function types 2. type alias 3. import alias 4. value class 5. data objectRevisions 1. fun interface (SAM) Many languages (like Java) did not initially treat functions as first-class citizens. They would emulate this functionality by using an interface with exactly on...| Kaushik Gopal's Website
The trick to understanding awk in all its terse glory is to understand its defaults. I made a screencast explaining how awk works by deconstructing a script I’d previously written for this blog 1. In this post we’ll look at deconstructing awk’s defaults so we can understand all those one-liner scripts stack overflow solutions throw your way. The example I have a file that contains the version info for my apps and I’d like to extract the first version number in there: // appVersion.gra...| Kaushik Gopal's Website
Great companies maintain their insurgent mindset, for fear of becoming complacent and irrelevant over time. Push decision making down to single-threaded DRIs Single-threaded is tech jargon that simply means solely focused on a single area. The single threaded DRI is the most senior person whose only job is to run a given product or initiative, this will typically be a product management or engineering leader. Leverage shared services to minimize duplication Done wrong, shared services can slo...| Kaushik Gopal's Website
I’d like to show you how I use Tailscale and a Mac mini in my office to achieve some nifty things. Tailscale is marketed as a zero-config VPN built on top of WireGuard that securely connects devices and manages firewall rules etc. While all of that might be true, think of it this way: Tailscale allows you to securely connect to a machine at home from anywhere on the internet. This includes your mobile phone, tablet, or laptop. Tailscale allows you to connect to a machine at home from anywhe...| Kaushik Gopal's Website
I’m always looking for legible, high-quality monospaced fonts for programming. I started with IBM Plex Mono, dabbled with a few others like Input Mono, even built a few from source like Iosevka, fell in and out of love with variousothers. In early 2020, the foundry ArrowType released Recursive which has now become my daily driver. What really got me hooked with Recursive —besides it being a gorgeous typeface— was the fact that it was open source and you could build it from source yourse...| Kaushik Gopal's Website
If you want to build a ship, don’t drum up the men to gather wood, divide the work, and give orders. Instead, teach them to yearn for the vast and endless sea. Antoine de Saint-Exupéry Lessons for Engineering Managers in Software.| Kaushik Gopal's Website
Icons by Yoolk Stumbled upon Yoolk’s website the other day. What a treasure trove of high quality icons. There’s even a github repo for some of these.| Kaushik Gopal's Website
icon by Yoolk If you’ve recently needed a text expander utility, might I suggest the trusty Keyboard Maestro1. I switched from TextExpander → Alfred quite some time back. Somewhat recently, I again switched from Alfred → KM for a couple of reasons: 1. One tool to rule them all Between work & home, I use multiple computers these days. Having to sync + maintain each of these different utilities across multiple computers is becoming tedious. Keyboard Maestro is a mainstay in my productivit...| Kaushik Gopal's Website
Two of the most common commands I run when I cd into a directory are: git status (which i do through git-number) ls -lh (aliased automatically as ll through fish) If this directory is not a git repo, then I usually am thinking of command 2. If however it is a git repository then I’d like to know if any files have been changed in this directory and which ones specifically (which is command 1). Wouldn’t it be nice if I could just hit the ↩ (enter key) and have this automatically happen? S...| Kaushik Gopal's Website
Whenever I need to convert, merge, or combine images or PDF files, I pull out my Terminal and attempt doing it first with CLI (command line interface) commands. Over time I’ve built an arsenal of CLI commands that 9/10 times does the trick faster than any other program. Prerequisites Most of the image manipulation commands require imagemagick and the PDF ones require poppler. Both of which are just a homebrew install away for macOS: # image utilitiesbrew install "imagemagick"# pdf utilities...| Kaushik Gopal's Website
A good friend of mine who’s worked on some pretty pivotal hardware/software integrations for our time told me: “it feels like a miracle when I see the code I wrote drive physical bits. I almost can’t believe it. No seriously… how does this even work?”. If this sentiment resonates with you to some level, you will love reading this article: The coming software apocalypse This entire article is fascinating. It took a lot of restraint not to just pull-quote every paragraph from this art...| Kaushik Gopal's Website
Recently, I killed an entire week moving from Things (3) → Asana → Todoist → Things. I won’t go into the details but I had a realization: I need to jot down how I think about my current system of productivity. Having this clearly laid out will convince future me that moving to another tool is unnecessary if I follow the existing one I have diligently. I also think it necessary to lay down tactical instructions, so that in my moments of weakness I have something easy to follow and prev...| Kaushik Gopal's Website
I use iTerm as my terminal of choice1. It constantly annoys me when I use Alfred or Spotlight that the Terminal.app (native macOS) app also shows up in the search results. This is especially annoying on new computers when Alfred hasn’t learnt my preferences as Terminal.app would show up first in the results. Options Quick googling shows two options: Add a Spotlight comment alfred:ignore Add the app to your Spotlight “privacy” Option 1 is made a little complicated owing to the fact that ...| Kaushik Gopal's Website
Fyi Henry is a theme I first open-sourced for Jekyll. You can read all about it here. I’ve now recreated Henry for Hugo. Why Hugo? Over the last year, I’ve been learning Go and my interest in Hugo piqued. Hugo—much like Jekyll—is a static blog engine written in Go. But it’s got more features, a more active community and is blazingly fast. Features Many of the features I wrote as custom features for Jekyll, come built-in with Hugo. But I took the opportunity to tweak these a little f...| Kaushik Gopal's Website
Fyi Henry is a theme I first open-sourced for Jekyll. I’ve now recreated Henry for Hugo after migrated this blog to Hugo. You can read about it here. I’ve used Jekyll as my blog engine here and meticulously tweaked it over the years to support a bunch of features. Many folks have asked me if I would ever put my theme up for sale or distribute it more widely. I’m happy to announce that it’s now available for free and open source. Introducing Henry - a Jekyll theme with a gorgeous readi...| Kaushik Gopal's Website
Given how many movies and TV shows we’ve been watching these days, it’s useful to have a personal rating system. I’ve used and tweaked this scale over time and it’s worked pretty well for me. How to use this system The scale ranges from 0-51 but coming up with a specific number off the top of your head is tricky. That’s where the associated descriptions comes in handy. Consider a movie and see if how you feel about the movie, matches with the associated descriptions. I’ve found th...| Kaushik Gopal's Website
From my 2020 post: 2019 has been the year that’s primed me the most for life changes. I imagine 2020 will the be the one where a lot of these changes materialize. … that’s cute. If you’re reading this in the future and suprised why, I suggest this Netflix mockumentary. Contagion style blazing dumpster fire year aside, it’s been hard to find the motivation to write this post. But reading my previous years’ posts, I’m usually grateful past me took the time to capture my thinking, ...| Kaushik Gopal's Website
The Bentwits So Ben Thompson1 recently tweeted: I’ve been using Android for the last couple of weeks, and honestly, the core OS is pretty good! The big problem is that Android apps are garbage relative to iOS apps. If developers actually care about pushing back against Apple they should give a damn. They don’t. He then went on to attribute the garbage quality of Android apps to developer laziness. This understandablyinfuriated some of us #AndroidDev unleashing the droid rage. To Ben’s c...| Kaushik Gopal's Website
If you’re in tech and have been thinking about your work and role in your company, I highly encourage you to watch this talk by Tanya Reilly1 Setting myself a reminder to rewatch this again 6 months from now. --- Such a phenomenal speaker and powerful story telling! Follow her @whereistanya ↩︎| Kaushik Gopal's Website
I’ve been looking into Tufte CSS recently. Tufte CSS -inspired by the teachings of the legendary Edward Tufte1- provides suggestions and tools to style web articles for improved legibility. I’ve started to incorporate some of those principles here while still trying to keep the authenticity of my original design. Most of these changes have been in the realm of CSS however the sidenotes feature was a slightly trickier beast. Fyi I’ve implemented this feature in my blog theme “Henry” ...| Kaushik Gopal's Website
If you’re a software engineer trying to be snarky, it’s important to get these terms right for maximum effect. What is Yak-Shaving? “Shaving a Yak” means performing a seemingly endless series of small tasks that must be completed before the next step in the project can move forward. Is this a good thing or a bad thing? It depends. Yak Shaving is sometimes very much necessary. It’s “bad” only when done unnecessarily. It’s unfortunate when necessary but might not be a bad thing ...| Kaushik Gopal's Website
Tip If you’re looking to just copy-paste instructions, jump to the section below. For the longest time, I’ve been rocking IBM Plex Mono as my programming font. While it has served me well, I started to experiment with some newer monospaced typefaces to see if I could find one that was even more legible1. That experiment quickly devolved into a rabbit-hole evaluation of a bunch of new programming fonts. Hello Iosevka Eventually, I landed up with the font Iosevka: It’s far more legible (c...| Kaushik Gopal's Website
Two big announcements: I made my first screen cast 1 I’ve updated the permalink title for all the blog posts here 2 I wanted to make sure that external blogs linking to previous post links wouldn’t break. So in order to do this, I had to edit all of my previous blog posts and add a redirect_from tag. Life is too short to be doing this manually so I whipped up an awk program to do it for me in about 20 minutes. It was so much fun building the program that I figured I should screen cast the...| Kaushik Gopal's Website
If you’re a programmer these days, you probably spend a large part of your day in git. If you’re a command line zealot like me, you realize the holy ways of using your Terminal app for everything and aren’t seduced by fancy GUIs that only stand to dissuade you from pure unbridled productivity. With that in mind, one typically finds themselves in a position where they have a few files that have changed liked so: If I had to add 2 out of those 3 files1, typing the commands start to get a ...| Kaushik Gopal's Website
2019 has been the year that’s primed me the most for life changes. I imagine 2020 will the be the one where a lot of these changes materialize. 2019 Recap Practice Vim for 30 days Not only did I successfully try it for 30 days, I now use vim as my primary text editor of choice and absolutley love it. It deserves a separate post though. Blogging + screencasting? I wrote 12 posts last year so I’m pretty happy with the 1-post-per-month average.I’m definitely looking to ramp up this number ...| Kaushik Gopal's Website
This blog now 1 uses Jekyll - a static blog generator that takes markdown as an input and pumps html as output. I then copy it over to my hosting server - Firebase, which then happily serves it to the interwebs. This setup has worked out swimmingly well thus far and has been rock solid. Even when my last post got high up the ranks of HN, my blog held steady. Not even the slightest of fears or signs of being fireballed or slashdotted. This is the beauty of HTML. To achieve the above, these are...| Kaushik Gopal's Website
Update I’ve since come up with an easier way to maintain my rules. This post talks of some of the cool things you can do with Karabiner. But if you want a more maintainable way of customizing all this, read my other post instead. tl;dr: brew install yqrashawn/goku/goku mkdir -p ~/.config && cd ~/.config touch karabiner/karabiner.json touch karabiner.edn # update your edn file with a sample from here https://github.com/yqrashawn/GokuRakuJoudo/blob/master/tutorial.md# or mine: https://gist.gi...| Kaushik Gopal's Website
Inspired by some well known architecture patterns like MVVM/MVI, I set out to come up with an agnostic set of principles that would help developers build features in their app in a robust, safe and (importantly) “testable” way. At Instacart, we’ve started to use these principles to build features on both iOS and Android. In this talk, we’ll examine these principles, discuss the merits (+ disadvantages!) and see how these can be implemented with precise code examples. Having implemente...| Kaushik Gopal's Website
This whole piece is such a biograpy treasure trove and one I’m filing under the “come back and read in a year” category. I’m highlighting some of the snippets in particular that really resonated with me: “This is going to allow people to watch video on our iPods, not just listen to music,” he said. “If we bring this product to market, will you put your television shows on it?” I said yes right away. I love how Steve was testing Bob with this decision. Could this still work? Ca...| Kaushik Gopal's Website
I use a 13" MacBook Pro at work these days. Android Studio frequently sent my machine into a tailspin. Over time, I’ve had to tweak and update my AS settings to make AS work well on the 13". I figured I should post them here for posterity and the benefit of other AndroidDevs battling with deathly slow AS experiences. I’m posting the abridged instructions and linking to the blog posts that led me to these settings, if you care for the details. Switch to a local gradle distribution curl -s ...| Kaushik Gopal's Website
The TestObserver is an RxJava staple for testing. It allows you to assert values in a stream, in the specific order they were emitted. Here’s a quick code snippet from the movies-usf repository1: @TestfunonSearchingForMovieBladeRunner_shouldSeeSearchResult() { viewModel = MSMainVm(mockApp, mockMovieRepo) val viewStateTester = viewModel.viewState.test() viewModel.processInput(SearchMovieEvent("blade runner 2049")) viewStateTester.assertValueAt(1) { assertThat(it.searchedMovieTitle).isEqualTo...| Kaushik Gopal's Website
I’ve been dipping my toes into some iOS development recently. Nothing too crazy, just pairing with some colleagues and trying to see how we can jointly improve the technical design on both platforms 1. It so happens that Apple just finished it’s annual conference WWDC, so I’ve been following the announcements closer this timer around. In that process, I ran across a tweet (from Jeff Nadeau who’s a developer working at Apple): Sort of blown away by the take that a min OS target is harm...| Kaushik Gopal's Website
This super intesting stack overflow answer explains why -in programming- if you have a sorted array, somehow magically it can seem like it’s easier to process each element vs processing the same array if it were unsorted. tl;dr - branch prediction With a sorted array, the condition data[c] >= 128 is first false for a streak of values, then becomes true for all later values. That’s easy to predict. With an unsorted array, you pay for the branching cost.| Kaushik Gopal's Website
Sometime back I ran across a thread where folks talked about this programming style called “Space Shuttle style” that the Kubernetes codebase followed. // ================================================================== // PLEASE DO NOT ATTEMPT TO SIMPLIFY THIS CODE. // KEEP THE SPACE SHUTTLE FLYING. // ================================================================== // // This controller is intentionally written in a very verbose style. You will // notice: // // 1. Every 'if' stateme...| Kaushik Gopal's Website
This is a fantastic post by Erik where he explains the nuance between IO-bound and CPU-bound operations in programming. … libraries have dedicated APIs for I/O scheduling work, separate from other types of operations …. but why is this the case? Why don’t we use a single thread pool for all background operations? The operating system will handle the scheduling of these threads the same I love how this specific question is framed (a good interview question for advanced mobile developers)...| Kaushik Gopal's Website
A not so well known api in RxJava is the .hide() operator. When does one use the hide operator in Rx? From the docs: Hides the identity of this Observable and its Disposable. Allows hiding extra features such as Subject’s Observer methods or preventing certain identity-based optimizations (fusion). there are a lot of complex operations that take place internally in RxJava (like internal queue creation, worker instantiation + release, numerous atomic variables being created and modified.) If...| Kaushik Gopal's Website
The Japanese can chalk this up to their creative laurels along with: the Fujifilm X100S the Sony walkmans and one of my favorite Anime.| Kaushik Gopal's Website
This feature is beneficial for projects defining custom source sets, since the compilation of independent source sets can be parallelized. In the case of multiplatform projects, targets for different platforms can also be built in parallel. For Android, the debug and release build types can be compiled in parallel. This sounds pretty cool, however I paused to think how often would i need the debug and release build types to be compiled in parallel? Probably CI like environment? oooo but with ...| Kaushik Gopal's Website
So i’ve been doing these kinds of posts for sometime now. Truth is i’ve been inconsistent with the format. Sometimes these are reflection posts (what happened last year) and other times they are resolutions posts (what i’m looking forward to in the next year). Usually it lands up being an amalgam of both, and I kind of like that personally. So i’m going to stick to keeping it a mishmash of thoughts as i begin the new year. 2018 in review: So the brother was married end of 2017 and whi...| Kaushik Gopal's Website
MBLT Dev 2018 Learn how to go to your existing old mobile app and refactor it into one with a powerful architecture. Slides| Kaushik Gopal's Website
We recently held our semi-annual hackathon at Instacart - the Carrot Wars 2018! In putting this hackathon together, I noticed a pretty blaring gap - there wasn’t a simple (and free) online service that would quickly tabulate the results for a hackathon event. We looked around and found some nifty options, but most of them were a tad bit too expensive for our liking. They also were not setup for a single event use or required a monthly subscription. There other usage restrictions, to...| Kaushik Gopal's Website
Discover how to break down the barrier between your hopes for a mobile CI/CD system and what’s available today using the powerful Azure toolset and App Center API’s. Go from an idea to a multi-platform React Native app powered by CI/CD in just a few steps. We’ll continue from there to learn how Logic Apps and Azure Functions helped power Instacart’s mobile development workflow from commit to a release to the store.| Kaushik Gopal's Website
This is such a fantastic post on how Apple sweats certain almost unnoticeable design details. I picked up a whole bunch of nuggets reading this article: …iPhone X rounded screen corners don’t use the classic rounding method where you move in a straight line and then arc using a single quadrant of a circle. Instead, the math is a bit more complicated. Commonly called a squircle, the slope starts sooner, but is more gentle. Here’ the wikipedia link to the mathematical shape Squircle. The ...| Kaushik Gopal's Website
Checkout this quick blog post I wrote for my company, tweaking the existing Kotlin TODO to work towards our requirements. While I don’t think this solution is a panacea for all your missing code snippets, I have found some luck with this method, in adding accountability for those PR review feedback comments you say you’ll get to, but conveniently forget :) Here’s a bonus if you’re reading this article from here: /** * @param month - regular month (so 3 = March) */@JvmOverloadsfunISDat...| Kaushik Gopal's Website
I’m obsessed with typefaces and fonts 1. My programming productivity is irrationally dependent on the font I pick for my IDE. I have spent unhealthy amounts of time experimenting and trying different fonts for programming. I usually prefer a monospaced font and I’ve bounced between Inconsolata and Consolas in the past – both truly beautiful typefaces. Recently though, a design director at Instacart shared this link on the laws of UX (a fantastic read btw). But —hot damn— I was smitt...| Kaushik Gopal's Website
We need more kindness and positivity in our online lives today. There is no side, that cannot benefit from that. Being rational or correct is futile without empathy. You can have opposing (or even incorrect) views but you have to find a kind and positive way to express that. You either learn you’re wrong or convince the other of your point of view. But everyone is more willing to have the conversation, if approached with kindness and positivity. A good first step for me is surrounding mysel...| Kaushik Gopal's Website
The Android development community today has embraced Rx(Java) in all it’s glory. But as developer’s understanding of RxJava has matured, they’ve started to peel back the layers and unleash its true power and potential. One such power is “Multicasting” where you get to share work across your app and reuse a whole bunch of stuff. This is really hard to do in general but Rx makes it really really easy. Rx itself though has a steep learning curve. But the easiest way to grasp the concep...| Kaushik Gopal's Website
2 part series This is a continuation post in a 2 part series: Understanding the changes Disposing subscriptions Disposing Subscriptions This was the part that I initially found most tricky to grasp but also most important to know as an AndroidDev (memory leak and all). Jedi master Karnok explains this best in the wiki: In RxJava 1.x, the interface rx.Subscription was responsible for stream and resource lifecycle management, namely unsubscribing a sequence and releasing general resources such ...| Kaushik Gopal's Website
In case you haven’t heard: RxJava2 was released sometime back. RxJava 2 was a massive rewrite with breaking apis (but for good reasons). Most dependent libraries have upgraded by now though, so you’re safe to pull that migration trigger with your codebases. Folks starting out directly with Rx2 might enjoy this guide but it’s the ones that started with Rx 1 that will probably appreciate it the most. 2 part series This is a continuation post in a 2 part series: Understanding the changes D...| Kaushik Gopal's Website
One of the advantages of working in the Bay area is you tend to run in to tech celebrities every so often. I was working in Palo Alto (late 2015) on a previous startup (Wedding Party). My colleagues and I decided to get coffee at the nearby cafe. I saw Andy Rubin sitting outside casually talking to two other folks. I was certain it was him and told my buddies, “Hey, I think that’s Andy Rubin”. My colleagues (the lovable jerks that they were) said: “that’s the Android fanboy in you s...| Kaushik Gopal's Website
I know it’s almost the end of January but I like to take my time with these posts. You can take a look at my previous year-end posts here. In addition to just jotting things I was most proud/happy about this year, I also want to note down some of my learnings. There were many overwhelming moments that led to much introspection. I want to try and document some of those moments here (atleast the less embarrassing ones). So here goes: Stuff I did: Fun stuff: met John Paul White : if you haven...| Kaushik Gopal's Website
We recently did an overhaul for Instacart’s shopper app and committed to using a presenter pattern for this. It turned out awesome! Presenters are not a new concept. They’ve been around since the dawn of software engineering time. But the devil is in the implementation details. If you have an Activity, RecyclerView, Adapter etc. at how many levels would you have the presenter? How does the use of presenters enabled super fast testing? How does the use of presenters enable constantly chang...| Kaushik Gopal's Website
Fyi This is a revised version of a talk I first gave in 2015. Slides| Kaushik Gopal's Website
I finished 2014 not having the slightest clue what would be in store. 2015 was a rollercoaster: I started a new podcast Fragmented (with my cohost and now friend Donn Felker), bought my childhood dream car (a Mini Cooper), got a new job (Wedding Party was acquired by Instacart), visited NY for the first time (for a talk I gave at DroidCon NYC) and finally - this one really stumped me - moved to San Francisco. The new year brings in a sea of sweeping change. With it I gain a little insight abo...| Kaushik Gopal's Website
What if you could get your UI tests to run as fast as your unit tests? you would write more tests you would feel happy writing the tests your managers would be pleased with you not goofing around with that new testing framework around the corner Using patterns of yore (like Martin Fowler’s supervising controller, effective use of presenters and view model state) we’re going to tackle everyday-real-annoying impediments to UI testing. We’ll address what parts of the UI need testing and ef...| Kaushik Gopal's Website
A common question most android developers have when using RxJava is: how do I cache or persist the work done by my observables over a configuration change? If you start a network call and the user decides to rotate the screen, the work spent in executing that network call would have been in vain (considering the OS would re-create your activity). There are two widely accepted solutions to this problem: store the observable somewhere as a singleton, possibly apply the cache operator and re-sub...| Kaushik Gopal's Website
List of blog posts on Kaushik Gopal| kau.sh