The Local Development Challenge

Developers used to live in a simple world with simple enough developer experiences.

Edit a file, run it, and test it. That’s it.

Unfortunately, that is no longer the case today. As a result of diverse technologies and software systems continuing to grow in complexity, the developer experience has become more and more fragmented.

To answer the question of how fragmented it has been already, let’s follow a day in the life of a web developer, named Mr. James Bond.

Mr. James Bond’s job involves working on a web application, which is architected in the popular Single Page Application + Microservices design style. The frontend is built in React and the backend is split into 3 services: user-service, order-service, and BFF-service (Backend For Frontend). …


Recently I migrated a few repositories from Gitlab to Github. Prior to that, I used Gitlab CI heavily to run CI jobs whenever we have new commits or merge requests to those repositories, and now I have migrated them into Concourse CI. This is an interesting journey and I would take the chance to share my takeaways for those two completely different CI systems.

Gitlab CI

Image for post
Image for post
Gitlab CI

Gitlab CI is a CI product that is builtin to Gitlab, the unique position brings it a few essential advantages:

  • no worries about how to checkout code from the repo — no secrets management, permissions etc
  • no worries about how to trigger builds, no matter it is for the pipeline of a specific branch like ‘master’, or for pipelines for merge…


Command line interface (CLI) development has come a long way from the simple “HelloWorld” program we built as our very first CLI app, to modern CLI apps such as `git` and `docker` which support complex patterns such as subcommands, many CLI options, and interactive outputs.

In this article, we would like to walk you through those modern technics for building an attractive CLI app with a concrete example — a command line clock.

Image for post
Image for post
terminal clock

For simplification purpose, we’ll build this application with Javascript and some npm packages, but the technics could apply to all languages.

BTW You can also read a version with code syntax highlight through Github at https://github.com/bencao/terminal-clock. …


We do a lot of testing today. Unit testing, integration testing, end to end testing. While a comprehensive test coverage is good, it does come with some additional costs, especially when different types of testing are mostly isolated and use totally different toolchains. Because you have nothing you can reuse which means to a tremendous amount of effort are needed for building each type.

In this article, we will describe a method which unifies many of those testing phases with similar components and standards, costing only a portion of traditional methods.

Image for post
Image for post
scalable testing

Personally, I don’t like terms such as “End to End Testing” and “Regression Testing” that much since they are vague by definition and understandings to those terms vary wildly for different persons. Instead, let us try to categorize by one factor only, which is the number of subsystems involved in a test. …


think twice before adding any complexities to your project

Image for post
Image for post

It was a year ago when I started an internal tool project called “integration CLI”, which was a command line tool for setting up a complete environment for the product we’re working on and later run tests against this environment.

The tool was built in nodejs. Coming from a background of a large single page application app, I was so used to the Babel + Webpack toolchain, that as a no-brainer, I kicked off the project with a classic .babelrc configuration, and started coding with the freedom I was used to in the SPA world.

In the package.json of the project, I had a script called “build” and another “prepublish” script which invokes the “build” to ensure that the source code is compiled from “src” folder to “lib” before publish, and should I remember to ignore “src” from being included into the published package to reduce the download size. …


Recent days I just wrote an active record extension to make cache optimization easier for company.
I realized it’s a useful tool and publish it as a gem might be a good idea.
So I start writing the gem ‘acts_as_method_cacheable’ yesterday afternoon, and I found it’s an interesting journey.
The home page is here.

Here are the steps I did it:

create a Gem with bundle

bundle gem xxx will generate a skeleton of a gem, the gem has a hierachy like this

Image for post
Image for post

write info in gemspec file

A typical gemspec file looks like this, which is quite straight forward.

Gem::Specification.new do |spec|
spec.name = "acts_as_method_cacheable"
spec.version = ActsAsMethodCacheable::VERSION
spec.authors = ["Ben Cao"]
spec.email = ["benb88@gmail.com"]
spec.description = "Make cache methods on ActiveRecord easy!"
spec.summary = "Instead of writing def expensive { @cached_expensive ||= original_expensive }, now you can write instance.cache_method(:expensive) instead. Also support nested >
spec.homepage = "https://github.com/bencao/acts_as_method_cacheable"
spec.license …


In the past a few months, I’ve tried to rebuild the classical FC tank game in CoffeeScript.

The final work is here.

Image for post
Image for post

Performance is always a bottleneck for rails apps. Why?
Maybe calling a method in other active records is way too easy, so we’re apt to call more, and delegate more.
But call and delegate is not free, it’s db operations under the hood, which are expensive.
Besides that, it’s very common that we bind many ‘before’ and ‘after’ callbacks on active record, which results in more and more CPU time during load.
To sum up, as rails developers, we’re very likely to encounter performance issue, so it’s better to equip ourselves with some swiss army knife.

Find out the problem

Before start optimizing something, the first step is to find out what the problem is. …


This article will focus on dockerizing existing rails app because it’s common and challenging.
But as long as a new app will eventually become old, you may find some tips here still be helpful.

If you’re like us, having an existing ruby on rails project and want to somehow run it inside a docker container so we can get those great benefits from the Docker ecosystem, this article may help.

TL;DR

There’re quite a few things we need to do to make our RoR app acts as a better container in the Docker world, and we can divide the task into several…


While browsing code these days, reading some wonderful pieces and some awful lines, some thoughts came into my mind.

Let’s start from some code smells first.

Smell 1 — Hide complexity/detail in a bad way

Case 1:

check_point!(:beauty)

What does it mean here? I have no choice but follow to the actual check_beauty method to see what happens. How about change it to:

should_have!(:perfect_shape)
should_not_have!(:big_mouth)
should_be!(:tender)
should_not_be!(:angry)

It’s inefficient to switch between different stack levels when reading code, human brain isn’t designed for that

Case 2:

if user_active?
send_promotion_about_beauty_product
end

Send beauty promotion to all users? Sounds like a huge waste. In fact, here is send_promotion_about_beauty_product:

def send_promotion_about_beauty_product
return unless user_female? …

Zhenhua Cao

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store