Entry No. 14

Using eager_load with order and Pagy in Active Model might cause the issue.

Origin

One week ago, our FCS QA/QC mentioned that the pagination info we displayed does not tally with the number of items we listed. Originally, I thought it is a simple bug, a bug caused by our presenter. We use a presenter in our listing page that can customize the info we want to display. Our presenter might filter out some data after we do the pagination of our data. But I was wrong about this.

After I traced Pagy’s source code and did lots of tests, I figured out the reason why we can not get the result we want. I will use a simple example to explain this and apply one solution to it below.

Scenario Simulation

Let’s say we have a website that allows different authors to post articles on it. And the readers can upvote the post to support the post they like. We have a page that lists all the authors and order by the upvotes of the author’s post. And the amount of the authors might be very huge, so we need to apply the pagination for it.

Reproduce The Issue I Faced

I create a sample app for this in Github. To focus on the topic I simplify the app a lot.

The next step is to add sample data. Let’s add at least 25 authors, two with two posts, two with one post and leave others with zero posts. Start the server and input the URL http://lvh.me:3000/authors in our browser and see what it will show.

The result will be sth like this.

As you can see, the pagination info shows items 1-20. But the number of authors displayed is 18.

As you can see, the pagination info shows items 1-20. But the number of authors displayed is 18.

Obviously, the pagination info does not tally with the number of authors. This is not what we want. What causes this and how could we fix this?

Investigate and Figure Out Why

Let’s take a look of the form app/forms/author_search_form.rb. This is the key to this issue.

class AuthorSearchForm

  attr_reader :results

  def submit
    @results = Author.eager_load(:posts).all.order('upvotes')
  end

end

Another key is that author to post is a one-to-many relationship.

The picture below shows how rails deal with this.

The first SQL is for Pagy to get the total number of authors. The second SQL is for Pagy to get the first 20 data. The third SQL is to get the info of related authors and posts.

The First SQL is for Pagy to get the total number of authors. The second SQL is for Pagy to get the first 20 data. The third SQL is to get the info of related authors and posts.

The purpose of the first SQL is to get the total number of authors. From the resulting picture above, we know the result is correct. The third SQL just gets the info by the id provided by the second SQL. And you can see that the third SQL get the same data twice with id 1 and 5. It seems that the second SQL has some issues. Let’s examine the second SQL carefully.

The second SQL is SELECT DISTINCT upvotes AS alias_0, "authors"."id" FROM "authors" LEFT OUTER JOIN "posts" ON "posts"."author_id" = "authors"."id" ORDER BY upvotes LIMIT 20 OFFSET 0. And the result of running it is on the picture below.

The results are ordered by upvotes for sure, but they have two duplicated ids.

The results are ordered by upvotes for sure, but they have two duplicated ids.

From this picture, we can know the reason why this happened. After we joined the table, the author with more than two posts will have duplicated data. Even though rails use SELECT DISTINCT in the beginning, [15, 5] is not the same as [80, 5]. (More about SELECT DISTINCT) When we executed the third SQL, we got the same data by only using the id from the result of the second SQL. That’s why 20 records became 18. Now we understand why this happened, then the next question will be that how could we fix this?

Solution

In order to solve this, we need to know what is SQL join. First, we need to decide how we going to order with multiple post authors. Let’s choose the max upvotes of it. The modified code will be sth like below.

class AuthorSearchForm

  attr_reader :results

  def submit
    @results = Author.joins(join_query).all.order('upvotes')
  end

  private

  def join_query
    'LEFT JOIN posts
       ON authors.id = posts.author_id
         And upvotes = (Select Max(upvotes) From posts Where authors.id = posts.author_id)'
  end

end

The pagination info tally with the number of authors displayed now.

The pagination info tally with the number of authors displayed now.

The numbers are the same now! But it seems that the logic is not correct. I want the most upvotes to be on the top and the author without a post to be on the bottom. The final code will be like sth below.

class AuthorSearchForm

  attr_reader :results

  def submit
    @results = Author.joins(join_query).all.order('upvotes DESC NULLS LAST')
  end

  private

  def join_query
    'LEFT JOIN posts
       ON authors.id = posts.author_id
         And upvotes = (Select Max(upvotes) From posts Where authors.id = posts.author_id)'
  end

end

Conclusion

Active Model provides a lot of functions for us to use. We may know when to use it, but we might not know how it works. Active Model also hides a lot of SQL queries from us. We should learn the concept of SQL and what query rails generate if we want to master Rails.

In this case, the key to it is very simple. We want to sort by the attribute of the post, but what about the author with multiple posts? We ignore this, so the issue appears. However, when the search form becomes more and more complex, then this is not easy to find out. Knowing how Rails generates SQL queries and the concept of SQL become more important.

Entry No. 13

Export big csv with Rails Active Job and Action Cable

Situation Overview

Exporting data was a nightmare to us all at FCS. We used to have it running directly in the controller, which causes system crash when client try to export, let’s say 15000 records. We tried optimizing the query, changing the data structures, etc. But none of it could solve the problem as long as the export code is still standing in the controller.

One week ago, I was paired with Austin(our team lead) to do some refactoring around our system, and I thought this should be fixed ASAP since this is a feature used frequently by our clients. So I did some research and discussed with Austin that what we could/should do is to move the export to a background job, so that it doesn’t block the main thread of the server anymore.

He thought it was a good idea, so I went on and implement it using Rails Active Job with Sidekiq. However, there was a problem with using Active Job, the job is executed in the background so it doesn’t inform the main server when it is completed. So we executed the job, got the exported file, and now what? We cannot give the file back to the server to return it to our client. This is where Rails Action Cable comes in.

Where it all started

So here I have an example controller with an export method to return the data csv


class DataController < ApplicationController

  def index; end

  def export
    respond_to do |format|
      format.csv { send_data ExportCommand.call }
    end
  end

end

and this is what inside app/commands/export_command.rb

  require 'csv'

  class ExportCommand
    def self.call
      sleep 10

      file = CSV.generate do |csv|
        (1..15_000).each do |_i|
          csv << %w[data1 data2 data3 data4 data5 data6 data7]
        end
      end

      file
    end
  end

And here it is in action

As you can see, the server doesn’t respond to any other request while it’s exporting. This is unacceptable.

As you can see, the server doesn't respond to any other request while it's exporting. This is unacceptable.

As you can see, this is definitely doesn’t work out. Now let’s move the export to background job so our web page can load properly.

Moving it to the background

rails g job Export

This command will generate app/jobs/export_job.rb. Now we move the export code to the export_job.rb file, and call the job inside the controller instead.

This is our ExportJob

class ExportJob < ApplicationJob
  queue_as :default

  def perform(data)
    ExportCommand.call
  end
end

So our controller will now be like this, it will just return 202 Accepted to the request and move on, the csv generation will now be handle in the background instead of in our main app

class DataController < ApplicationController

  def index; end

  def export
    ExportJob.perform_later
    head :accepted
  end

end

Now let’s see how it goes, remember to have sidekiq running or the job will not be performed, open a new terminal tab, go the the project folder and run

bundle exec sidekiq
Now it runs smoothly. But where's our file? (゚ー゚)
Now it runs smoothly. But where's our file? (゚ー゚)

We can see that no file is returned. The reason is as I said before:

The job is executed in the background so it doesn’t inform the main server when it is completed.

Action Cable to the rescue

In order to return the csv file to the client, we will create a channel using Action Cable and broadcast the file back when it’s ready.

First, we generate a channel called ExportChannel by this command:

rails g channel export

This command will generate a bunch of files you need to make the channel work export channel

Now we will config cable to use Redis to broadcast our data, go to config/cable.ylm and do

redis: &redis
  adapter: redis
  url: redis://localhost:6379/1

development: *redis
test: *redis

production:
  adapter: redis
  url: <%= ENV["REDIS_URL"] %>
  channel_prefix: your_project_production

Next, we will create a subscription to our ExportChannel, go to app/assets/javascripts/channels/export.coffee and change its content to:

# This is to call this function in a nother coffee file
window.ExportChannel ?= {}

window.ExportChannel.Subscribe = (export_id, callback) ->
  App.export = App.cable.subscriptions.create({
    channel: 'ExportChannel'
    export_id: export_id
  },
    connected: -> callback()
    disconnected: ->
    received: (data) ->
      blob = new Blob([data['csv_file']['content']]);

      # Create a link with the data and trigger click event to download the file
      csv_download_link = document.createElement('a');
      csv_download_link.href = window.URL.createObjectURL(blob);
      csv_download_link.download = data['csv_file']['file_name'];
      csv_download_link.click();

      # Re-enable the export btn
      $(".export-btn").html("Export Data")
      $(".export-btn").removeClass("disabled");

      App.export.unsubscribe()
      App.cable.disconnect()
      delete App.export
      return
  )
  return

We wrap the subscription inside a function that receive an export_id param so that it only trigger when the button is clicked. After receiving the data, it will disconnect from the channel and terminate itself.

Now that we have the subscription, we will edit the channel to match our subscription. Change the content of app/channels/export_channel.rb to the following

class ExportChannel < ApplicationCable::Channel

  def subscribed
    # Export id is sent from button click in web client
    stream_from "export_channel_#{params[:export_id]}"
  end

  def unsubscribed; end

end

Then we will add the code to broadcast our file in the job so it will return the csv when the job is performed

class ExportJob < ApplicationJob
  queue_as :default

  def perform(export_id)
    csv_content = ExportCommand.call

    ActionCable.server.broadcast(
      "export_channel_#{export_id}",
      csv_file: {
        file_name: 'data.csv',
        content: csv_content
      }
    )
  end
end

And we need to pass the export_id from the params to the job so that it’ll be able to broadcast to the correct channel.

Finally, we’ll make the button generate an UUID and append to the URL then subscribes to the channel on click, we will also disable it and re-enable it when the data is returned, go to app/assets/data.coffee and do:

$(document).on 'turbolinks:load', ->
  $('body').on 'click', '.export-btn', (e) ->
    uuid = generateUUID()
    # Disable Export btn
    $('.export-btn').html("Exporting...")
    $('.export-btn').addClass('disabled');

    # Append UUID to the URL
    URL = decodeURI(e.target.href + '?export_id=' + uuid;)

    # Subscribe to the channel
    window.ExportChannel.Subscribe(uuid, ->
      $.get encodeURI(URL)
      return
    )

# https://www.w3resource.com/javascript-exercises/javascript-math-exercise-23.php
generateUUID = ->
  d = new Date().getTime()
  'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace /[xy]/g, (c) ->
    r = (d + Math.random() * 16) % 16 | 0
    d = Math.floor(d / 16)
    (if c is 'x' then r else r & 0x3 | 0x8).toString 16

and we’ll add an extra class to the button in the view so it’s easier to identify, this is our app/views/data/index.html.erb

<div style='display: flex; justify-content: center; margin-top: 120px;'>
  <%= link_to 'Go to home page', '/', class: 'btn btn-primary'%>
  &nbsp;
  <%= link_to 'Export Data', data_export_path, method: get, remote: true, class: 'btn btn-primary export-btn' %>
</div>

Now let’s run it again

Voila. There's our file, and we can also goto other pages while at it.
Voila. There's our file, and we can also goto other pages while at it.

That’s it. Now we can do both the export and other stuff at the same time. The only note I’d add is that this method will create 2 jobs, 1 is when we click the link, the other is when we modify the link and call get method again. This might raise some performance issues.

Sidekiq server log

As you can see in the sidekiq server log, it started 2 jobs for 2 request. The temporary fix for this is to add a guard clause to the job so that it returns when there is no export_id. Like this:

class ExportJob < ApplicationJob
  queue_as :default

  def perform(export_id)
    return if export_id.blank?

    csv_content = ExportCommand.call

    ActionCable.server.broadcast(
      "export_channel_#{export_id}",
      csv_file: {
        file_name: 'data.csv',
        content: csv_content
      }
    )
  end
end

Then it will decrease the time of the 1st job by a lot

Sidekiq server log after optimized

That is it for now, if you have any other solutions. Feel free to share with us. Until next time.

This demo project is available on github

Entry No. 12

Reduce rework with Behavior Driven Development

A memorable Friday

It was a Friday morning and the end of a sprint too. I had already submitted my code for the second task the night before for review. Everything was chill and good. It seemed to be one of those productive weeks and I could “R.I.P” in the weekend.

It was about time for lunch when I received an urgent request from our front-end team to change a few things on the first task that I had already finished earlier on Tuesday. To my surprise, I asked myself “What could possibly go wrong?”.

The change request was to fix the format of the respond from the API I created earlier. Our front-end team could not parse the respond without throwing some exceptions because some expected and required attributes had not been included in the respond. After spending some time trying to figure out why my respond could not be parsed, I learnt that id of the respond was expected to be UUID, and a meta object with total_pages attribute was also required in the respond.

“Why didn’t you have these attributes correctly in the first place?” you might ask.

When I started working on my API, I looked at the respond from a few other APIs. The respond included id in the form of the UUID, and every respond has meta attributes which included total_pages used for pagination. The purpose the API I was working on was different from the previous APIs though, so I thought to myself, the respond could be different. Since this time our server would generate the ids, so there was no point using UUID. The data could always be returned in one page, so pagination could be removed.

With these thoughts in mind I could only see the pros they bring:

  • Table performance improvement since UUID was out of the picture
  • Smaller code base with less complication and easier to maintain

The only con that I just discovered was:

  • Our front-end team could not use the API :)

At this point I realized that the rest of the day was not going to be good because I had two unfinished task hanging over my head and only a few working hours left before weekend officially started. The stress and anxiety began to creep in. Everything turned from good to bad so quickly.

After a few hours of stress and help from my colleagues, I managed to fix the respond to fit our front-end team requirements. This time though, I did not forget to cross-check with them before submitting my code and calling it done with the task. However, the API could not finish on time to be deployed, so the customer could not use this feature maybe until the end of next week.

The task that I finished so early in the sprint came back and bit me on the leg. What I thought was a productive week turned out not so productive after all. Rework is definitely the silver bullet that kills productivity and I couldn’t help but wonder how to improve my workflow to stop the rework.

Search for a few minutes on the internet, I came across an article about Behavior Driven Development a.k.a BDD. BDD was no stranger to me though. It was taught in one of the classes I took back in university, but … without any actual context. In order words, it didn’t make much sense to me back then. Having re-reading BDD after all the task rework I went through, the ideas and concepts of BDD finally make much more sense.

Behavior Driven Development a.k.a BDD

cucumber.io has excellent resources on BDD. This section of the blog will be a summary of the info I managed to collect mainly on cucumber.io and some other articles.

BDD overview

Behavior driven development is a set of practices that aim to reduce wasteful activities in software development.

The most common wasteful activities are:

  • Rework caused by misunderstood or vague requirements
  • Technical debt caused by reluctance to refactor code
  • Slow feedback cycles caused by silos and hand-overs

If you already read through the earlier part of the blog, you might realize by now, the causes of my task rework were all among these wasteful activities :)

BBD aims to reduce these wasteful activities by introducing practices that will narrow communication gaps, proster better understanding of the customers’ needs, and promote continuous communication. All of these are done around real word examples.

BDD can be split into two main parts:

  1. Deliberate discovery
  2. Test driven development

Deliberate discovery

A common reason for task rework is a misunderstanding of how the feature should behave and what the problem we are trying to solve is. We often assume how the feature should work and think in just our point of view. Because of this we only see our part in the play and how we want the feature to work. It’s easy to forget about other people and teams that also work on the same feature. The worst part is we might also leave the customer, the one that actually uses the feature, completely out of the picture.

According to cucumber.io, it’s shown that teams which deliberately seek to discover what they are not clear about before starting development are more productive because there’s less rework. The most effective way to deliberately discover the ‘unknowns’ and ‘unclears’ is through effective conversation between the stakeholders.

cucumber.io has a simple yet effective technique to help clearing out the ambiguity of requirements/stories called Examples Mapping. It’s just a short meeting (25 minutes max) which involve the stakeholders having conversations about concrete examples of the requirement/stories that are going to be developed.

Test Driven Development a.k.a TDD

After all the requirements are clear and the team decides to move the task/story card to development, it’s time to write … tests. TDD concepts are rather simple:

  1. Write tests
  2. Run the tests
  3. Write/refactor code to make the tests pass
  4. Repeat

This might seems a little backward, but the tests are actually guidelines to help us focus on the desired behaviors that are intended especially if the tests are developed and written after the rules and examples from earlier deliberate discovery step.

In my experience, having tests before writing code reduce testing time and effort, because the data is already set up and I can just target the test I want then let it run without me having to manually navigate and click on the UI.

Nowadays a lot of frameworks support TDD and provide excellent test suits which allow developers to write tests that are easy to read and close to natural language. If you are using Ruby on Rails, rspec is an excellent gem for writing tests that are very easy to understand.

All in all

BBD perfectly points out the reasons why I had such a memorable Friday and has the solutions to offer. Another benefit that I can see which was not mentioned is that deliberately discovering the problem domain allows you to see more clearly what and how long it takes to solve the problem.

Of course it would be meaningless if we don’t put any of this into action. If you have been through what I have, then why not try this out for yourself. Use this blog as a guideline or any other source that fits you best and apply BDD to the next few task/stories.

Here is to become a better developer. Cheers!

Entry No. 11

The 3 skillsets: Programming, Design, Product

There are 3 skill sets in this industry - development, design and product.

These skills exist in every attempt to build software. They exist in Google, and Facebook, and Intuit, and small dev shops. It’s useful to recognise skills as falling into one of the three buckets, because then you know what to optimise for.

Development is the simplest to understand. Programmers write code while building software. Most of the software produced today is complex and demand coordination between different programmers, and sometimes different teams. So at the higher levels of this skill tree, development includes skills necessary to coordinate between many programmers.

Design is also relatively easy to understand. Interfaces can be easy or difficult to use. A good interface designer is able to come up with user interaction flows that make sense to the user. Often, designers are the ones who have a first stab at a feature, because asking a programmer to design the UI for a feature is a Really Bad Idea.

Software companies hire less designers than they do developers. It’s normal to have 1 designer for a team of 5 or more programmers. Often, the configuration of teams in software companies is one designer attached to every team. So the iOS team has one designer, and the Android team has another designer, and so on.

Some designers are able to code. The Django team built their web framework with the assumption that their designers would be able to write simple HTML and complex CSS. Other designers use tools like Sketch, due to its ability to export assets for direct use by the developers.

At the higher levels of this skill tree, designers are able to do A/B tests, user interviews and are able to set tone via a design language, for the entire company. It’s no accident that Facebook uses the same shade of blue and the same icon style everywhere, for instance.

The last skill set is harder to explain. It is also the rarest in Asia. “Product” is the skillset that glues together developers, designers and business concerns in a given product.

Product managers operate in between the core concerns of a product. Have you ever seen a building where the developers kept adding wings and extensions and towers, all in slightly different styles? The building eventually becomes ugly and unwieldy. The same goes for products. Product managers prevent this from happening.

It would take a whole blog post to describe what a PM does, so I’ll leave you with this one, possibly the best I’ve seen on the topic: The Product Management Triangle. Dan Schmidt does an incredible job describing the challenges and tensions of the role, and why it’s tricky to define the PM’s workload.

The upshot of this is that you have the 3 basic roles that are directly involved with building a modern digital product. What role you’d like to take would be defined by these silos, and it should be a useful tool to evaluate the skills that you are learning today, for the job description you want tomorrow.

This post is part of the FCS Career Playbook for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 10

Dealing with change in the IT industry

When I first told my parents that I wanted to study computer science, my father took me aside and asked me: “Are you sure? The computer industry changes very quickly. Are you willing to keep learning new things, and throwing old things out, for the rest of your life?”

I told him I was sure I could take it; I couldn’t imagine a world in which I wasn’t learning new things.

I realise now that I was naive. When you grow older, you grow to have additional responsibilities. Some of us grow to take care of one’s family, and many of us grow to have additional interests and obligations.

This growth doesn’t hide the fact that it is true that in my father’s career, he did not experience as much volatile skills change as I have already experienced in the comparatively short career that I’ve had. It is also true that if you’re a programmer in this industry, you will need to keep up with technological change.

Wisdom from Older Programmers

The good news is that our industry has seen a bit, and we’ve got leaders who are willing to share their experiences online. (I don’t think the same can be said of many other industries - law or teaching or banking, for instance).

See Tim Bray, the co-creator of XML, in his reflection of his long career in software:

Should you stay tech­ni­cal? The bad news that it’s a lot of work. We’re a young pro­fes­sion and we’re still work­ing out our best prac­tices, so the ground keeps chang­ing un­der you; it doesn’t get eas­i­er as the decades go by.

The good news is that it doesn’t get hard­er ei­ther. Once you learn to stop ex­pect­ing your knowl­edge to stay fresh, the pace of in­no­va­tion doesn’t feel to me like it’s much faster (or slow­er) now than it was in 1987 or 1997 or 2007. More good news: The tech­nol­o­gy gets bet­ter. Se­ri­ous­ly, we are so much bet­ter at build­ing soft­ware now than we used to be in any of those oth­er years end­ing in 7.

And an­oth­er thing that may not be ob­vi­ous: It’s not a one-way door. I stepped off the tech­nol­o­gy train, spent years in start­up man­age­ment and tech­nol­o­gy evan­ge­lis­m, and climbed back in­to en­gi­neer­ing life with­out too much pain.

It’s worth it to read the rest of the article, as it’s got some really good arguments for going into management, VC, startups or big companies; Bray’s been in most of them, and has thoughtful comments on the rest.

Ideas not frameworks

If you accept the idea that learning compounds (as we’ve discussed in the second essay in this series), and that the more you learn when you’re young, the easier it is to learn new things when you’re older, then you must also accept the corollary: that the ideas you learn are more important than the specific technologies that are used to implement them.

Or, to use a stupid example: once you learn for loops in one language, then you will automatically understand for loops in every language that has them! The idea is more important than the language.

Similarly, this idea applies to systems as well. It has been said that “Those who do not understand Unix are condemned to reinvent it, poorly”.

There is truth in the pithy saying. While technologies emerge, are hyped, and are seen to replace those that are older, in reality, very little is truly new in Computer Science. Long before React’s idea of the virtual DOM was popularised by Facebook, game programmers accepted as standard the idea of updating models and having the equivalent sprites redrawn, automatically, in a render loop.

Witness, too this essay by programming language researcher (and Aspect Programming co-creator) Crista Lopes. She laments that nothing truly new has emerged in programming languages since the 90s.

Whether this is true is not the point (Jean Yang’s work on enforcing information flow policies at the language level may be truly novel, for instance) – the point is that there aren’t many languages today with completely alien ideas in them.

All this implies that there is a set of ideas that one can learn, and if one learns a large enough set, one becomes more resistant to the winds of change. With this in mind, software engineering becomes less like ‘throwing everything out and learning everything all over again’ (as my father argued), but more like learning new iterations of old, proven ideas.

And that, hopefully, shouldn’t seem very scary to you.

This post is part of the FCS Career Playbook for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 9

How To Be a Successful Intern

We’ve had a number of technical interns here in FCS over the years. Some do really well: by the end of their internships they find themselves delivering major projects directly to clients. Others don’t do as well. Here are some things we’ve noticed are common to the more successful ones.

Before we dive into these common factors, though, let’s talk a little about internships in general. What should you be looking for in an internship?

Internship Goals

The key to understanding internships is that you’re there to learn two things:

  1. Technical skills. This is a no brainer: you’re a programmer, you take on a software engineering internship to learn real-world technical skills. The way code is written in the industry is different from school, and this is where you get to learn that difference.

  2. Work/life exposure. The actual experience of working in a company. This is what people refer to when they say they’re looking for ‘people with job experience’: what they actually mean is that working in a job involves setting the right expectations. People expect new employees to come in with the right attitude, calibrated to the job they’re hired to do.

Most interns we meet at FCS know that they should be focusing on learning all the technical skills they can. And this might be obvious to you too. But what is interesting is that you should also be maximising your work exposure.

This is not very obvious. Some new hires we’ve seen come in with vastly different expectations. Some expect to be spoon-fed skills. Others are unhappy if they are assigned work that they aren’t interested in. An internship is the best place for you to learn what your expectations should be.

As an intern, you’re in the unique position of being able to see the inner workings of a company, without being tied to it. An internship is just a temporary job, after all. You don’t have to stay after your n months are up. This is both an disadvantage and an advantage.

The disadvantage is that sometimes, you can’t see how the whole company works because you’re the most junior person in the room. The advantage, however, is that you can compare across multiple companies (this is true if you do multiple internships). Comparing across internships is how you figure out what kind of company you would like to work for in your career.

(I strongly urge you to consider doing at least 2 internships – one at a big company, and one at a small company during your university life. Find a way to make it happen.)

While you’re at the internship, take the time to learn everything you can about the company. How does it make its money? Who are the best engineers? What is the leadership like? What weaknesses do you notice about this company, and how might you make it better if you were in a position of power? How are conflicts resolved, and how are engineering decisions made?

Talk to your manager, and make friends with the seniors above you.

These seem like irrelevant questions, but they turn out to be very important in your career. Knowing how a company makes its money teaches you to see if you’re in a profit-centre or a cost-centre. It also tells you what the most valuable jobs look like in other, similar companies.

Company weaknesses are even more important to notice: they might not be a deal-breaker to you right now as an intern, but if the full-timers in your company are quitting because of something, then you know what to watch out for it in the future companies you apply to.

3 months is long enough to pick up on a broad set of experiences, if you’re willing to put in the time and listen. Ask the full-timers what career and life decisions they’ve made, and then decide for yourself if you want to make the same decisions in your life.

Now let’s look at some qualities the best interns seem to share:

1. Knowing when to ask questions

This is tricky. One of the most annoying traits a junior employee can have is the tendency to keep asking questions about the most basic things. This is annoying because you begin to waste the time of senior employees, whose time is more valuable than yours.

As a junior employee, you do want to be effective, and it is true that you know less than your seniors. So what’s the right balance between asking for help and struggling with your problems by yourself?

I have two ideas that may help:

The first idea is to ask questions according to the following template: “I have a problem with X. I have tried A, B and C, but it doesn’t work. Instead, when I tried A I got bad result P, when I tried B I got bad result Q, and when I tried C I got weird result R.”

Until you are able to give a list of approaches that you’ve tried and failed, don’t ask a senior.

The second idea is to time box stuff you don’t understand. Need to implement a feature and don’t have any idea how to do it? Give yourself X minutes, set a timer, and then at the end of those X minutes ask a senior.

The first idea forces you to make sufficient effort, and the second idea prevents you from wasting too much time when some guidance may be useful.

2. Ask for regular reviews

Internships are a great opportunity to get real industry experience. To maximise this opportunity, maximise the feedback you get.

If your company has some form of monthly managerial review, that’s great. But even if you do have these reviews, given the limited amount of time you have at a company, it’s probably a good idea to get informal reviews from seniors at a higher frequency than just monthly.

These reviews could be as simple as “hey, could we have a quick chat about that project I worked on this week?” with your primary manager. And if you’ve collaborated with seniors from other teams, it might make sense to approach them for some feedback at the end of the week, or the end of the collaboration as well.

3. Work harder than a full-timer

Now, before I begin on this, let me say up front that work/life balance is important to get right in your life. Work/life balance is so important to the rest of your career, in fact, that I urge you to figure out your limit as an intern, instead of figuring it out while you’re a full-timer.

What do I mean by this? Well, the stakes for burnout are much lower as an intern than as a full-timer. Internships are book-ended by academic semesters, because you get to go back to school after an internship is over. And internships are good places to level up, seeing as you have a clear amount of time, and clear goals to achieve. Pushing yourself to get to those goals within the set timeframe is an obvious thing to do.

This is probably going to be controversial, but I recommend using your internship as an opportunity to figure out where your limits are, so you know when to stop when you’re finally working as a full-timer. Work late into the night, try one or two all-nighters, and most importantly, notice when you become resentful about the work you’re doing.

Resentment is the best signal I know that burnout is on the horizon. If you feel it, you know that burnout isn’t far away. And you’ll have learnt something important about yourself, I think, something you won’t have to learn the hard way when you’re working full time at a job.

This post is part of the FCS Career Playbook for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 8

Small but Effective

This short document will outline some skills and attitudes that would help you with your engineering career at Floating Cube. Engineers receive this document during orientation.

Floating Cube is a small company, and will likely remain small compared to other companies for some time. As of 2016 we are dedicated to building a small but effective team of engineers, who will be building up the foundation of all our future products. Notice what’s not in that sentence: it doesn’t say professional, or perfect. We don’t care that you wear nice clothes to the office. It instead says small and effective. Let’s talk about what this means.

Small teams allow individual engineers to make a large impact on the company. Being small also means being exposed to a lot of technologies and aspects of the business, and having the opportunity to build for the future.

Effective teams demand ability to execute. We care about how well you contribute to or accelerate the development of the rest of us. In return, we will take your growth seriously, and help you perform better for our benefit. By the time your time with us is up, our aim is that you will be able to leave at a higher level than when you came to us.

Here are some skills that would help you during your tenure here:

Debugging ability

Many things will break as Floating Cube grows. This includes code, modules during deployments, or processes (aka the way we do things) as we scale our company up. Your job as an engineer will include recognising when things are broken and pointing it out to us with the aim of fixing things.

Fearlessness to dive into something you don’t know

Being part of a small team means that you will get to grow faster. How this actually happens is that you’ll be exposed to other aspects of building product that most engineers in a larger company won’t. To experience this, you must be fearless to dive into things you don’t know.

Don’t be afraid to modify 3rd party software. Don’t be afraid to dive into your teammate’s code to fix something for a client. Don’t be afraid to call a client to ask for more information, or debug his problem, or even visit his shop in Singapore to see how your software runs. All these things will make you better at building product.

A pragmatic approach to decision making

It’s nice to sit down and talk about best practices, or the ideal ways to do development. But in a small organisation, pressing technical or business problems exist today. This may sometimes mean doing non-optimal technical, process, or people-related things.

A useful rule to use is to ask yourself “what action will increase the probability that the whole team succeeds?” when facing one of these decisions. Know when to get things done, but know also when to push back to make things better. Pick your battles for the benefit of the team.

A tool building mindset

By definition, a small but effective team means that we have to increase the productivity of every member of the team. Building tools is an engineer’s solution to get more done with the same number of people. Do your work with an eye towards automation, or streamlining processes to make everyone’s lives easier.

A strong generalist mindset

Floating Cube is at the stage where we’re building many new platforms for our future products. This may include using a new programming language, operating system, or framework tomorrow. All our engineers are expected to be able to pick up new things on the go. (We think this is the right attitude towards a career in our industry, anyway). Be prepared to move to a new platform tomorrow.

Be a player, not a victim

There are two responses to every event: we can either be victims and blame any problem (a slipped project deadline, a product launch that flops, or conflicts with teammates) as being due to external circumstances. Or, we can be players, and identify the aspects that are within our sphere of influence and focus our energy and efforts toward what we can actually affect and fix. Do the latter. Be a player. =)

Grit, combined with a willingness to learn and introspect

Grit is the ability to keep at something over a long period of time. Applying grit to self improvement will benefit everyone at the company, but most importantly yourself.

Floating Cube does reviews once every month. Use these sessions to reflect on the challenges you’ve faced in the past month. Focus on what you’ve learnt on your job, and what you’ve learnt about yourself while meeting your challenges. Then work with your manager on what you’d like to aim for in the coming month.

Featured image from Soreen D on Flickr, original content for this piece was by Edmund Lau on Quora, but adapted for FCS’s onboarding process.

Entry No. 7

The Value of Side Projects

When doing recruiting for Floating Cube Studios, I’ve found it rare to find students who have had side projects. Most of the candidates I’ve interviewed have only shown me school projects. I’m not completely sure why that is.

One possible reason could be that the university holidays here in Vietnam aren’t that long. Another could be that many students take on part-time jobs during the semester and during the school breaks – often, these roles aren’t technical. Students wait tables and help out in shops instead of taking on programming-related jobs.

And yet, when it comes to finding a software engineering job, successful, well executed side projects are often the easiest way to measure a programmer’s ability.

Even the very fact that you have side projects sends a signal to a potential employer that you at least like programming.

I want to argue that building side projects is the single most value-added activity a young programmer can be doing. These projects are even more helpful for those who get bad grades in school, yet still want to work in software engineering.

Here’s why.

  1. Side projects indicate interest and motivation. You don’t come back from school and code on a side project if you aren’t self motivated. Side projects that you build out of interest tells me, as an employer, that you’re interested in problems outside of school. And if the project is successfully completed, it tells me that you have enough self motivation to see something through to the end. These are incredible skills that are valued in any programming role.

  2. A portfolio of side projects also indicates exposure to external technology. The very best IT schools don’t teach specific technologies or tools. They instead teach the basics of programming and app development, and trust that the student will be able to go out and learn the rest on his or her own. This makes absolute sense: no university can constantly keep up with the latest developments in software engineering! Side projects are the easiest, if not the best way to learn cutting-edge development practices.

  3. Side projects provide a good way of measuring skill. Why do companies hire people with good grades? Well, one reason is that grades are a way of measuring your ability. Companies think that candidates with good grades will translate to programmers who have good skill. However, in IT we can measure your skill directly: by reading your code! At FCS, we don’t look at grades so much. We read the candidate’s code, and listen to him or her speak about it. Students with bad grades can get hired in IT if they show they can write good code.

In fact, this last point has an even stranger conclusion: if you don’t have a degree from a University, or you graduated with a non-IT degree but can code, apply to software firms. You’re likely to get a job anyway.

It’s important to recognise that this is a huge advantage in our field. The ability to measure future performance directly, instead of using grades, means that anyone can become a software engineer. It also means the best way to become a good programmer is to program, not to take tests!

How do you get started?

There are many free books and resources related to learning new programming languages or frameworks. But it’s important to not spend too much time reading them (without actual coding).

The best way to get started on a side project is to find an interesting problem to solve. Ideally, your first problem should not require a solution that is too complicated to build.

I still remember the first side project I built: I had a friend in university who had a problem with parking in his university. Every once a month, the students at his school were required to sign into the university website and apply for a parking slot. This service was a first-come-first-serve basis: the first 200 people who submitted their details after 8am on the 1st day of the month got the parking space. So, on the 1st of every month, hundreds of students would camp by their computers, refreshing the page repeatedly for the button to appear.

I was in my first semester of university, and I had just learnt programming. I thought I could help him by writing a script to do everything automatically for him. The script could then loop repeatedly until it has succeeded in booking a parking slot.

As it turns out, this was a very useful project to do. As an excuse, I chose to learn the Python programming language, and then to learn to set it up with cron on a CentOS server I had just bought. It took me many painful hours, but I eventually got it to work.

Today, Python is my favourite programming language. And my friend never went without a parking slot for his entire university life.

A few other things that may help:

  • Use IRC when you are stuck and need help. If Google fails, and repeatedly banging your head against the wall doesn’t work, log in to freenode and go to the language channel to ask for help (e.g. #PHP if you are programming PHP, #Django if you are building something in Django, and so on).
  • If that fails, use StackOverflow!
  • Last, but not least: here is a list of free books you can use to start your learning.

Happy hacking!

This post is part of the FCS Career Playbook for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 6

Learning Many Frameworks vs Specialising In One

One of the most surprising things I’ve learnt about software engineers in Saigon is that many want to specialise in just one programming language or platform.

This is surprising to me because this attitude isn’t as common in Singapore. Software engineers in Singapore would at least say that learning new things is a good thing, even if they don’t really practice it.

But some Vietnamese engineers that I’ve spoken to have told me that they think learning new things – especially new things outside their circle of competence – is bad!

Some of them tell me that this is old Vietnamese wisdom: that if you specialise in more than one skill, you won’t be a master in any of them. Some tell me that their professors in University teach them to do this. And I am not the only one to have experienced this attitude: other software project managers have confirmed seeing this opinion in Saigon.

The net result is that I’ve met Vietnamese engineers who refuse to code in or learn platforms that are outside their selected speciality. For instance, Android engineers who refuse to touch iOS, or PHP engineers who refuse to write backends in any other language.

So which should you pick? Should you stick to one framework, or be the generalist that does all?

The answer to this isn’t that simple. It’s not true that one is good and the other bad. The real answer is this: whichever you pick, ensure your ability to learn new things does not disappear.

Learning is Painful

My main worry whenever I hear a Vietnamese engineer tell me that they don’t want to learn a new platform is that they’d forget how painful it is to learn something completely new.

This may sound strange if you’re fresh out of university, or currently an IT student. “Learning isn’t that painful!” you might say, “It’s normal!”

But give it a few years. Once you’ve spent 10 years, for example, getting good at iOS or PHP, you’ll find that learning something completely new can be very painful, especially in comparison to coding in a framework or language that you’re already an expert in.

This is especially dangerous in our industry, where things change quickly. Maybe today you’re a well-paid, valuable Android engineer. But if over the course of the next 5 years Android dies, or if Google decides to switch Android to a completely new language, you’ll be forced to learn something new or risk being unemployable.

Let’s be clear: the risk isn’t that you’ll suddenly get fired. The risk is that you’ll slowly get stuck in a company, never being promoted, and then when you’re finally let go you find that getting a job is suddenly a lot more difficult.

The flip side of this is that engineers who can learn quickly are often regarded as more valuable than engineers who can only do one thing. Companies like Google, for instance, never hire software engineers based purely on programming language skill: instead, they test programmers on algorithms and problem solving ability. Their reasoning? If you’re smart enough to pass an algorithms interview, you’re smart enough to pick up whatever language you’ll need to pick up at Google. More importantly, you’ll be smart enough to keep learning new languages as the company’s needs change.

But Learning Takes Time

There is, however, a flip side to this. It is true that constantly learning the shiniest new thing will come at the cost of being very good at one platform. You cannot become a master of one thing if you are dividing your time to learn many new things.

Also, I’ve met senior engineers in Vietnam who tell me that their families are more important to them. They don’t have that much time to learn new things, so why not spend it on getting good at the one thing that they already know and use? This is also true.

The truth is that both concerns are valid. This is why my argument isn’t to pick learning many things vs learning just one thing, but to ensure your ability to learn new things does not disappear. So long as you keep some base level of learning around, you’ll do fine regardless of which view you take.

This post is part of the FCS Career Guide for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 5

Profit Centres vs Cost Centres

Profit centres vs cost centres is something I wish someone had told me earlier in my career.

This idea applies to just about any job you do, no matter what industry you’re in. It is a powerful way of looking at your work, and figuring out how good the job would be for your career in the long run.

Here’s how it works:

There are two kinds of places you can work in:

  1. You can be working in a profit centre, or
  2. You can be working in a cost centre

A profit centre is a job that makes money for the company. For example, if you’re working in a bank, the bankers are the profit centres – they’re where the bank makes most of its money. If you’re working for a tech company, the programmers are the profit centres. If you’re working for an accounting firm, the accountants are the profit centres. You get the idea.

Companies also have cost centres. These are places in the company that are regarded as the cost of doing business. So for instance, in a company like Google, the finance department and legal department are regarded as cost centres. They’re not directly tied to how Google makes its millions and millions of dollars each year; instead they are regarded as people you have to pay in order to get business done. On the other hand, banks regard their IT departments as cost centres. The bankers make all the money while the programmers are a cost of modern banking.

Here’s what this means for you: all things being equal, work for a profit centre, not a cost centre.

1) If you are in a profit centre, the company will regard you as one of the most important parts of the company. After all, how well you perform is linked directly to how much profits it gains!

2) Therefore the company is highly motivated to invest in you. People working in profit centres enjoy lots of invisible benefits: the company will spend more on them, will train them better, will work hard to keep them. On top of that, companies will try and recruit the best people to work in their profit centres, which means that your fellow colleagues, your managers, and their bosses are likely to be really good people you can learn from.

3) New projects that you want to push are more likely to be approved. You will have more freedom to start new initiatives. And so on so forth.

On the other hand, if you are working in a cost centre, you’re likely to suffer from a lack of invisible benefits. New initiatives are harder to push through, your colleagues won’t be as heavily recruited, and the company won’t work so hard to keep you.

This idea explains a lot about job and salary types. It explains why salespeople tend to be amongst the highest paid regardless of industry – because the sales force is directly linked to how much money a company makes. It also explains why programmers in Google enjoy more benefits than programmers in large banks.

Notice that the ‘profit centre vs cost centre’ argument does not say anything about how much you’re paid. If you are a lawyer in the legal department of a large company, you would probably be paid just as well as if you were working in a law firm. But you will learn less.

One last note: this idea also means that sometimes, the best way to get what you want is to position yourself as a profit centre to your boss, as opposed to a cost centre. Internal company politics are built around appearances. If you are in a cost centre, your best strategy is to sell yourself as a profit centre.

It can be entirely possible that an IT department is regarded as a profit centre inside a bank, if the head of the department knows how to sell his team as important to the bank’s long term goals (or if the CEO thinks IT is important).

Here’s a real world example: working in AIA’s IT team in Singapore is pretty good, because the current AIA CEO believes technology will be a huge competitive advantage for its business. The current team is paid well, and given quite a bit of freedom to innovate.

All things being equal, work for a profit centre, not a cost centre.

This post is part of the FCS Career Playbook for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 4

Salary vs Growth?

As a fresh graduate, should you go after a high-paying job, or look for places you can grow?

My answer to this is deceptively simple: so long as the job pays an acceptable salary, ignore salary and pick a job where you can grow.

Or, to express this as an SQL query:

SELECT * FROM jobs WHERE salary > x ORDER BY learning_rate

Why Companies Pay High Salaries

A high salary can be a very unreliable metric to use. This is because companies pay high salaries for one of two reasons: i) they pay you because you’re good. Or ii) they pay you well because the job sucks.

(There’s actually a third reason: because these companies are from overseas, and can afford to pay high salaries, but I’ll talk about that in a bit).

As a fresh graduate, you’re not likely to be very good. You may be on your way to being good, you may be a genius at exams, but unless you created Linux in University, like Linus Torvalds did, you simply aren’t worth as much. Therefore it’s more likely that the company is paying you a lot because the job stinks, and people don’t want to do it.

How can a job stink? Well, when I was just out of university, some of my highest paid friends worked on oil rigs, for petroleum companies. They were petrochemical engineers, and they were paid highly because they would live on oil rigs for months at a time, far away from friends, family, and good food.

Similarly, outsourcing companies sometimes pay high salaries, especially when compared to the average wage. This is usually a Very Bad Sign. These companies do this because you’re not going to learn as much. They also do this because their work is so soul-crushingly boring (imagine integrating SDKs for crappy games day-after-day) that you’ll want to shoot yourself in the head after a bit.

Now, I’m not saying you should get a job with a low salary. What I’m saying is: don’t be motivated by salary, at least not when you’re a fresh grad.

Instead, evaluate the job on other characteristics. So long as the job pays >= average, look at whether the job will allow you to grow faster and become better than all your peers. The second criteria matters more than the first.

Evaluating jobs like that will also allow you to pick jobs from overseas companies that pay high simply because they can. For instance, a company that sells software in the US makes a lot of money, so they can spend a lot on employees in Saigon when they open an office here. This is one situation in which a high salary does not mean a lousy job.

Why Choose Growth?

If salaries aren’t as important, why choose personal growth?

This is obvious if you pause to think about it. Remember when I said that companies pay good salaries because you deserve it? Well, a few years down the road, you will become good enough to justify a high salary. And your friends who started out of college with sucky-jobs-that-paid-well wouldn’t be so easily promoted.

They wouldn’t be so easily promoted because of two reasons: firstly, the rate at which you learn compounds. The more you know, the faster you learn. Sooner or later, you leave those who don’t learn as much behind.

Secondly, we are in an industry that rewards learning. The software world changes very quickly. People who don’t learn to learn, especially in the early years of their careers, will be crushed by the rate of change in this industry.

It is for this reason that I believe picking a job where your rate of learning is high will be the most important thing you can do for your career. This is especially true when you are young.

“Wait a minute!” some of you may say, “That’s not true! Some companies promote you based on how long you’ve been with the company. Others promote you based on how many years of experience you have on the job.”

The best companies in our industry value skills, not years of experience on the job. The companies that _do _ask you for your years of experience aren’t companies that you want to work for anyway. (Think about it: do you want to work for a company who promotes people based on seniority? That isn’t likely to be a company that you want to work for, because your boss is likely to be an idiot. Why is he likely to be an idiot? Because all the good people leave).

A good way of thinking about this tradeoff is that some jobs allow you to invest in yourself. Others allow you to cash out on your skills.

When you’re a fresh graduate, out of university, pick a job that allows you to invest in yourself.

Good Signs

How do you know a company is a place where you can learn a lot? Well, there are a few signs. When you’re interviewing with them, ask the following questions:

  1. Does the company take employee growth seriously?
  2. Does the company provide good mentorship?
  3. Are there code reviews?
  4. Is there a structured on-boarding program for new hires?
  5. Does the company provide you with books, or send you to seminars?

Some of the answers to these questions depend on the kind of company you work for. Product companies and certain kinds of consulting companies, for instance, are more motivated to grow their employees. Outsourcing companies and certain IT departments aren’t.

Be careful which kind of company you work for. Your learning rate matters to your future career.

This post is part of the FCS Career Playbook for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 3

The Value Chain of Software Companies in Vietnam

If you’re a software engineer in Vietnam, there are 4 types of companies you can work for. These companies exist on a spectrum of value. As you consider what kind of company you would like to work in, it pays to pause and consider each option.

Currently, Vietnam’s tech ecosystem has the following types of companies:

  • Outsourcing companies
  • IT departments of large, non-IT companies
  • Consulting companies
  • Product companies

Outsourcing companies

Outsourcing companies take a spec and turn it into code. Roles in these companies are sometimes called ‘code-monkey work’ – you’re just a programmer that has to implement whatever is given to you. Examples of some outsourcing contracts:

  • A games company in Europe wants integration of some analytics SDKs in their portfolio of apps, but doesn’t have enough manpower in their games development teams to do so. They hire a relatively cheap software company in Vietnam to do this for them. Your job: to integrate libraries across a dozen different apps.
  • A financial services company wants to build a stock tracker app for their customers. They hire a company in Europe. The European company sits down with the financial services company to understand the requirements, and then writes a spec. They then hire an outsourcing company in Vietnam and give them the spec. The European company pays the outsourcing company and keeps the rest as profit.

Outsourcing companies make up the majority of software companies in Vietnam – and naturally, they’re not very high-value places to work in. This is problematic for you, as a software engineer. Because outsourcing companies compete on cost (the cheaper service wins), software engineers at outsourcing companies will be pushed to be fast, not good.

Therefore, there is only so much you can learn in an outsourcing company.

An IT department of a large, non-IT company

IT departments build technology solutions for their company. This parent company is usually not an IT company.

This type of software engineering job is an interesting one to work in. For instance, you could be a software engineer in a bank, building the bank’s website or mobile services. Or you could be a software engineer for Proctor & Gamble, building internal tools for their managers to use.

Jobs in IT departments can be good or bad. How good your job is depends on how important the department is regarded inside the parent company. If the parent company regards the IT department as a valuable and strategic part of achieving its goals, then you will do well as a software engineer. On the other hand, if the parent company regards the IT department as a ‘cost-centre’ (i.e. the IT department is just the cost of doing business) then it would not be a very good software engineering job.

The tricky thing about this is that it’s often impossible to see how important the department is to the parent company until you’re already inside. The best trick to decide if it’s a good place to work in is to get to know someone who is already working inside the company, and then to ask him or her.

Consulting companies

Consulting companies build apps for clients. They look a little like outsourcing companies, but they’re not. For starters, consulting firms are supposed to come up with solutions for business problems. They do more than converting a list of features into code.

Let’s say, for instance, that a bank wants to build an app to increase usage of its credit card products. A consulting company would be hired by the bank to figure out the app strategy, the feature list, the deployment plan and the look and feel of the app. The consulting company then executes on all of this, while giving advice to the bank.

This is a consulting company, not an outsourcing one: the consulting company provides guidance to the bank on the best way to achieve the bank’s goals. The best consulting companies act like partners to their clients: both equally invested in their client’s success.

One large advantage of working in a consulting company is that you get to explore new technologies as you wish, for client projects. Of course, some clients want their projects to be implemented with a certain technology. But occasionally clients don’t care, beyond wanting the app to be done. In those cases engineers are free to pick the programming languages and frameworks they would like to use.

(Floating Cube Studios, by the way, is a bit of a mix – it is both a consulting and a product company).

Product companies 

Product companies are companies that build and own their own products. Because the engineers own the codebase of the product they’re working on, product companies tend to invest more time and energy into training and growing their engineers.

This applies to small companies like Ticketbox.vn, as well as large companies like Google, Facebook, and Atlassian. There’s a lot more nuance to whether a product company is good to work for (things like is your boss good, do you get along with your colleagues, are you being paid enough), but all other things being equal, product companies are good places to work in. The only trade-off is that you would not have an excuse to play with new technologies for each new project as you would in a consulting company.

Conclusion

If you’re a programmer in Vietnam, you need to consider your career prospects carefully. Where you work determines what kind of growth you would have as a software engineer.

If you have the opportunity: pick companies that are higher up in the value chain. The more value your company provides, the more opportunities you will have to learn. Which is to say: if you have a choice, don’t work for an outsourcing company. It’s not good for your career.

This post is part of the FCS Career Playbook for Software Engineers in Vietnam. Check the guide for more software engineering career advice.

Entry No. 2

A Redesign, 5 Years Coming

It’s been 5 years since Floating Cube Studios first set up in Singapore and Saigon. We’ve gone though quite a bit since then: built apps for clients a couple hundred times our size, saw the evolution (and ever-escalating war) between Android, iOS and their respective app stores, and finally launched of a couple apps of our own, to varying degrees of success.

Today, I’m pleased to announce that we (finally) have a new web site, with special thanks to FCS’s design team (and specifically, Cong, who saw through the development of this from conception to deployment).

In many ways, this post is yet-another-random-firm’s-prognostication-while-announcing-something-boring-like-a-new-website blog post. Probably nobody will read this. But I want to pause here to note that we’re currently in the midst of a change. Floating Cube’s been through 5 years of app store exuberance. Those early years of the mobile rush – along with the optimism and easy successes – are long past.

Hieu, the technical lead, Trung, the design lead, and I are currently seeing through a change in direction for Floating Cube’s next few years. Asia is still at the cusp of a digital revolution unlike anything the West has ever seen. If you think of the first 20 years of the Internet as belonging to the West, then I’d wager the next 20 will see wide-scale changes in the wake of spreading information technology – and that most of the changes that matter will occur in Asia.

Being in Singapore and Vietnam thus gives us a unique opportunity: we’ll be in the centre of these changes – or at least a short flight away from most of them. But saying that is the easy part. Building a company to take advantage of that uncertain future is our real challenge.

Here’s to seeing how it goes.

Cedric – Project Manager,
Floating Cube Studios

Entry No. 1

Everything you need to know about how our blog works.

Awesome picture, init? Picture caption located outside the grid to the left of the picture like this.
Awesome picture, init? Picture caption located outside the grid to the left of the picture like this.

Body text for the blog section will be a 10-columns centered container. The font will be Georgia to enhance the legibility of the blog post. Let’s have a little history lesson about this typeface, Georgia. According to Wikipedia, Georgia is a transitional serif typeface designed in 1993 by Matthew Carter and hinted by Tom Rickner for the Microsoft Corporation, as the serif companion to the first Microsoft sans serif screen font, Verdana. Microsoft released the initial version of the font on November 1, 1996 as part of the core fonts for the Web collection. Later, it was bundled with Internet Explorer 4.0 supplemental font pack.

Georgia is designed for clarity on a computer monitor even at small sizes, partially effective due to a large x-height. The typeface is named after a tabloid headline titled “Alien heads found in Georgia.”

The Georgia typeface is similar to Times New Roman, but with many subtle differences: Georgia is larger than Times at the same point size, and has a greater x-height at the same actual size; Times New Roman is slightly narrower, with a more vertical axis; and Georgia’s serifs are slightly wider and have blunter, flatter ends. Georgia incorporates influences from Clarendon-style typefaces, especially in b, r, j, and c (uppercase and lowercase). Figures (numerals) are an exception: Georgia uses text (old-style) figures whereas Times New Roman has lining figures.

That was an interesting lesson for you. Did you notice the link to Wikipedia up there has a different colour? That’s how links are supposed to be styled. Now let’s see some quote and its style, shall we?

“I have a dream!” – Martin Luther King Jr.

The quote uses the font Circular by Linotype. And it has a different color as well, same as hyperlink. The font size is 36px. That’s pretty much what will be in a blog post. Let’s make this post a little longer with dummy text.

Oh but wait, last thing to include is some styling for the code tag. Let’s do it.

//a bunch of code goes here

if((1+5)==(3+2)){

print “Equal”;

} else {

print “Not equal”;

}

That’s it. Pretty simple isn’t it? Since the blog post is finished we will have an option to comments, likes and share this post.