• Why Unit of Work is an anti-pattern but not Repository

    Why Unit of Work is an anti-pattern but not Repository

    Is Repository and Unit of Work (UoW) an anti-pattern? In the .NET/C# world, it is often said that Repository/UoW is an anti-pattern and one should probably use Entity Framework Core directly.

    But if it is an anti-pattern, why are people still using it? Even Mosh Hamedani – a respected YouTube coding trainer whom I follow – wrote about common mistakes when applying this pattern. Surely it must be popular.

    Purpose of the Repository/UoW Pattern

    Let’s talk about why this design pattern exists. It is actually a type of Adapter pattern and the primary use case is for separation of concerns between domain (or “business logic”) and infrastructure (or “data access”).

    The other motivation for using this pattern is to allow mocking repositories for unit testing.

    Must Repository go together with Unit of Work?

    It is also very common to see the Repository pattern used together with the Unit of Work (UoW) pattern. The UoW pattern is added to manage transactions – a feature of relational databases to perform ACID operations.

    However, there is increasing tolerance for eventual consistency and less atomicity; fully ACID operations are starting to matter less these days as software adopts the microservice architecture.

    So unless you are a bank, or dealing with critical financial data, maybe building your software with transactions management – a feature that is specific to RDBMSes – might not be the kind of dependency you want.

    Why is UoW an anti-pattern sometimes

    I’ll start by saying that everything depends on your use case, but for me – I tend to feel that Unit of Work (but not repository) is an anti-pattern.

    Let me explain why.

    You see, the repository interface can be described in its simplest form as an interface for read/write operations.

    // What a typical repository looks like
    public interface IMyRepository
    {
      MyObject GetById(int id); // Read
      IEnumerable<MyObject> SearchByName(string name); // Read
      void Update(MyObject object); // Write
      void DeleteById(int id); // Write
    }

    I’ll use an analogy here: In good old C, the standard input/output header defines basic read/write operations. The interface <stdio.h> is an abstraction of the underlying data access implementation and is a close example of the repository pattern – the interface doesn’t care if you are writing to the console, to a filesystem, or to a serial port – just like a repository interface shouldn’t care if it was an RDBMS, or a CSV file, or even a remote API call.

    Does <stdio.h> expose specific features of a particular filesystem or a serial port? No. So why should a specific feature of an RDBMS (transaction management) be depended upon outside of a repository interface?

    userRepository.Update(user);
    unitOfWork.Save(); // If this was not done, the record will not be updated!

    Using the C example from earlier: Imagine having to always call fsync() (from <unistd.h>) after calling fwrite() in order to commit changes – does it make sense? Sure – you may call fsync() if you wanted to force your changes to disk immediately, but you do not and should not have to explicitly call it.

    (In .NET there is Transaction Scope, but that is a topic for another day.)

    How much to depend on the RDBMS?

    RDBMSes are great tools with important features, but as an application architect, I often ask myself if it really matters to the application I am building.

    Sure, almost 99% of the time the RDBMS is unlikely to be switched for anything else. Heck, in some applications it may even be the same version of MySQL for the rest of the application’s life – that’s probably because many applications were designed with a database-first approach (and I have another blog article coming up about why a database-first approach should probably be avoided.)

    So you may think, YAGNI – let’s not over-design the application. Maybe in such a case, you may be better off without the Repository/UoW pattern entirely, but… this is 2021, and you are unit testing your code, rightttt?

    Unit tests and mocks

    If you have ever attempted to mock an ORM framework, you’ll know it is pretty impossible. Sure, EF Core has an In-Memory Provider that can be used for testing, but that has a lot of caveats.

    As a result, it would be easier to apply the repository pattern instead of attempting to mock the ORM framework.

    Mocking the test, or testing the mock?

    Ever had unit tests pass but integration tests fail because of database constraints? Ever tried testing code that relied on a transaction rollback? Mocking the behavior of an RDBMS is extremely difficult, and spending half our lives trying to mock how an RDBMS works shouldn’t be the case because we do not want to end up testing our mocks instead.

    // Typical use of UoW
    try
    {
      userRepository.Update(user);
      unitOfWork.Save(); // This commits the transaction
    }
    catch (Exception ex)
    {
      unitOfWork.Rollback();
    }

    Example: How would you mock and test the rollback?

    Instead, we should implement repositories as if we were writing data to regular storage – think of it as writing to a CSV file, memory, Redis cache, or something else.

    Do CSV files have transactions? No.

    Then, maybe we should not use Unit of Work:

    try
    {
      userRepository.Update(user);
    }
    catch (Exception ex)
    {
      // Log an error and fix it manually, retry the operation, place
      // the update in a queue to be processed later if you really HAVE 
      // to make this update, otherwise just throw the exception!
    }

    The generics phenomenon

    The typical Repository/UoW pattern is to make each repository represent a single domain entity, e.g.

    public interface IUserRepository
    {
      public void GetById(int id);
      public void Create(User user);
      public void Update(User user);
      public void Delete(int id);
    }
    
    public interface IGroupRepository
    {
      public void GetById(int id);
      public void Create(Group group);
      public void Update(Group group);
      public void Delete(int id);
    } 

    And as a result, it is common to have these further reduced to a generic interface to reduce the repetition on CRUD methods, e.g.

    public interface IRepository<TEntity>
    {
      public void GetById(int id);
      public void Create(TEntity entity);
      public void Update(TEntity entity);
      public void Delete(int id);
    }
    
    public interface IUserRepository : IRepository<User> { ... }
    public interface IGroupRepository : IRepository<Group> { ... }

    However, quite a large number of applications I have written do not use the full CRUD operations on every single repository. Some tables are read-only, some never require an update, some never get deleted.

    The N-N relationship

    Next, how do I add a user to a group, or assign a group to a user?

    Create yet another repository for the intermediary N-N relationship table and insert a record!

    public interface IUserGroupRepository : IRepository<UserGroup> { ... }
    
    // Usage
    var userGroup = new UserGroup(userId, groupId);
    userGroupRepository.Create(userGroup);
    unitOfWork.Save(); // Always remember to save!

    This is why implementations of the Repository/UoW often end up with a crazy list of interfaces and classes, and it’s probably not easy for a developer to figure out which repository to use. Is it called UserGroup or GroupUser? @#$%^&

    It is also extremely counter-intuitive to be actually creating a new object. In a regular object-oriented code, it would probably be written like this:

    group.AddUser(user);

    Why aren’t repositories written more expressively?

    Unlike <stdio.h> in C that I used as an analogy earlier, repository interfaces are not doing byte-level I/O operations – it handles more complex data types, so methods should therefore be written more expressively.

    For example, why not write the User-Group relationship methods in such a manner?

    public interface IUserRepository 
    {
      public void AddGroup(int userId, int groupId); // Inserts into UserGroup
      ...
    }
    
    public interface IGroupRepository
    {
      public void AddUser(int groupId, int userId); // Inserts into UserGroup
      ...
    }

    Even better – if your application will never ever see the need to store Users and Groups in different data stores, why not simply combine them into one repository interface?

    public interface IAccountServiceRepository
    {
      public void CreateUser(User user);
      public void CreateGroup(Group group);
      public void CreateUserWithNewGroup(User user, Group group); // Can use a transaction
      public void AddUserToGroup(int userId, int groupId); // Inserts into UserGroup
      ...
    }

    (Imagine you were writing to the UNIX /etc/passwd and /etc/group – how would you implement it?)

    One may argue that I’ve come full circle and am replicating a UoW but at the same time also violating the single-responsibility principle. Then again, what is the “single responsibility” of a repository? Often the term “single responsibility” is being taken out of context from what the originator (Robert C. Martin) had expressed it to be: “A class should have only one reason to change”. What external or structural influences may cause the interface above to change?

    Lastly, if CreateUserWithNewGroup() required a transaction for an atomic operation, shouldn’t the transaction be managed at the repository rather than by the domain? Should the onus of transaction management be placed on the domain layer or the repository layer? Is handling transactions in the domain logic also violating the single-responsibility principle?

    Conclusion

    Once again, if your software or company really, really, really depended its life on having consistent data in an RDBMS, by all means, continue to use the Repository/UoW pattern (or simply use the ORM directly since it is a hard dependency.)

    But for a large majority of cases, YAGNI. A single repository interface alone is probably good enough.

    This blog article was more of me thinking out aloud than trying to encourage or influence a change in how people implement repository/UoW, and comments are most certainly welcome.

  • Teachers – the unsung heroes

    Teachers – the unsung heroes

    Not his first “skool”

    My First Skool (MFS) isn’t Ethan’s first school; he had transferred from another private school which shall remain unnamed (although it is noteworthy that it was a well-known franchise.)

    Ethan joined MFS at Nursery level (age 4). At the time, Ethan had just gone through 4 main teachers, 2 principals and countless part-time “assistant” teachers, plus 2 hand-foot-mouth-disease (HFMD) episodes, and it was an incredibly difficult time trying to encourage his return to school. He was excited to go to a “new school” for the first week or two, but his excitement weaned quickly.

    Every parent probably thinks their kid is a genius, and I was no different. Some of his “achievements” include being able to name both primary and secondary colours by age 2, identify almost every single brand of car on the street by age 3, and even discern differences that sets almost similar car models apart (Lamborghini Huracan Performanté vs Evo – I can barely tell the difference!)

    As a kid, he was also incredibly observant, catching details of things we usually wouldn’t notice. I was led to believe he has a photographic memory.

    At 2-3 years, he was also able to remix words into the tunes of nursery rhymes:

    两只car car,两只car car,跑得快,跑得快。
    一只没有headlight,一只没有taillight,真奇怪,真奇怪。

    Ethan, ~3 years old

    However, Ethan had always seemed distracted and restless in class. Teachers from his previous school and also MFS had highlighted this, but over time, his behaviour seemed to have improved – especially in MFS. I would be lying if I said I hadn’t at some point thought he might be ADHD/ADD.

    The bad experience

    It is not until much later now at the age of 6 that Ethan had finally explained why he did not like going to school: his (previous) teachers were very fierce and always scolded him, and he hated that they simply “dragged” him to class. Thankfully, he had not expressed the same sentiments for his teachers at MFS.

    Given his incredible memory for things, it is likely that his early experiences left a scar in his mind that school is “not fun”. He might, at some point, have even been traumatised by the constant change of faces and treatment from different teachers when at the age of 2-3 children are mostly seeking security from familiar faces and battling separation anxiety.

    I am glad that Ethan’s attitude towards school has improved ever since he entered MFS – with much credits to teacher Stefanie, Zhou 老师 and teacher Celine. While most of Ethan’s previous teachers only complained of his inattentiveness and restlessness, there was only one other teacher from the previous school (who eventually resigned) who observed that Ethan was a little different – similarly, the teachers at MFS then expressed that while Ethan seems distracted, he is actually listening and capable of answering questions afterwards. Of course, I understand that his restless behaviour is, however, a distraction to both the teacher and classmates, and needs some work.

    Finding MFS, and the dedicated teachers was a matter of sheer luck during a time of desperation as I sought to get Ethan out of a disastrous pre-school experience, but should not be taken for granted. MFS (or at least the branch Ethan is in) had the operational scale and capability to provide a good support structure for the teachers, and that has helped the teachers remain dedicated and committed. With scale, it makes manpower planning easier. With scale, it is able to hire more teachers or assistants to relieve workload when required. With scale, teachers have a growth path in their career.

    The primary school rush

    Ethan will be enrolling for primary school in a few weeks’ time. I am more convinced than ever that it is not necessary to get into a name-brand school, and could never understand the kiasu-ism that surrounds P1 registration. I believe that in every school there will be good and bad teachers. As long as there isn’t terrible peer influence (which is more a function of the location/neighbourhood than the school’s reputation), any MOE school in Singapore is possibly a decent school.

    Not shown accurately in P1 registration data is the population of the applicants in the neighbourhood versus the capacity of nearby schools. The popular schools in each neighbourhood tend to have a disproportionally high oversubscription ratio which feeds on itself year after year, and has no direct correlation to the actual quality of the school’s teaching staff, management and curriculum delivery style. For example, Clementi is an incredibly dense neighbourhood, and no doubt Nan Hua Primary may be a good school, the high oversubscription ratio might be just a function of town population.

    I was paying almost 3 times more (before subsidy) in a private name-brand franchise school, which is clear that even “throwing money at the problem” could not guarantee my child’s early formative school experience. Fancy award-winning programmes, music and dance, arts, whatever it may be, had little actual effect on the child’s development if teachers are overwhelmed or have no passion in their work.

    It is my belief that a school that is not overwhelmed with students and demanding parents will likely function better, and hence, using a similar logic – an over-subscribed primary school may not always be better. Of course, there are arguments that lousier schools have other things to deal with – such as bad students – but what makes one think that good schools don’t have bad students?

    The role teachers play

    Teachers should not underestimate the impact or influence they have on every child. Children spend most of their waking hours in highly developed countries like Singapore in school. Pre-schoolers are in school for an average of 45-50 hours per week – more hours than average adults are at work.

    Teachers work even longer hours then – they have to prepare for materials, be in school before kids arrive, and leave only when the last child has left. Rain or shine, COVID or HFMD. Passionate, dedicated and committed teachers like Ethan’s teachers at MFS are the under-appreciated unsung heros of our modern, highly-educated society.

    I, too, hope that one day I can become a teacher and contribute back to society. Without our education system and teachers, Singapore wouldn’t have been what she is today.

    Wishing all teachers and those in the education profession an advanced Happy National Day and a Happy Teachers’ Day 2021 – thank you!

  • Stop returning null

    Stop returning null

    Have you ever debugged a null error? It’s like a void space. The error often doesn’t tell you anything. Null handling sucks the life out of developers.

    Developers should stop returning null. Modern programming languages have exceptions – use them.

    There was a time when we avoided throwing exceptions, because exception handling is thought to be slow, and has other criticisms as well.

    However, returning null instead of throwing an exception is far worse.

    Let me explain.

    If you were tasked to write the implementation of this method to retrieve a user:

    public User GetUserById(int id);

    If the user with value of id is not found, you are probably tempted to return a null value.

    But what is null? Is it an invalid id value (e.g. id <= 0)? Is it because the user is not found? Is it because maybe the user record has been disabled?

    In most cases I have come across, a null return would mean that something erroneous has happened. “User does not exist” is an error!

    All is fine if your team is disciplined and religiously handle null across the entire application, but chances are very slim because it is quite difficult to consistently handle null when built-in types (such as int or double) will never be null.

    Uncaught null exceptions are terrible to debug, not only because the null exceptions don’t tell you much, but also because it often requires back-tracing many lines of code to figure out how and why you got a null.

    Uncaught null values are no different from uncaught exceptions, and if you have been writing code long enough you’ll know that null exceptions are one of the most common exceptions you have to debug.

    If a developer above had thrown something like UserNotFoundException for the method/function above, life would be so much easier – even if it was uncaught. Making it a habit to throw an exception as part of input validation or error handling forces you to think about the error scenario and error message.

    Null is bad for health. Null exceptions are like black holes. Null is less than nothing…

    “What do you mean less than nothing? I don’t think there is any such thing as less than nothing. Nothing is absolutely the limit of nothingness. It’s the lowest you can go. It’s the end of the line. How can something be less than nothing? If there were something that was less than nothing, then nothing would not be nothing, it would be something – even though it’s just a very little bit of something. But if nothing is nothing, then nothing has nothing that is less than it is.”

    E.B. White, Charlotte’s Web

  • I hate paper

    I hate paper

    I hate paper, really. From when I was in Secondary School I always wondered why we cannot have our books on floppy disks and load them up on a computer.

    In the late 80s, the whole world switched from paper to plastic to reduce deforestation. Plastic cups and bags are more economical and easier to make, lighter to transport, and stronger for the same material density. Suddenly the whole world now wants to switch back to paper products.

    It is 20 years since the height of the “dotcom boom”. Governments, banks, insurance, telcos and other stupid corporate institutions are still sending me tonnes and tonnes of paper every day which I have to take additional effort to scan, shred and then sort into recycling bins. Some are still sending me paper letters even after I have opted for electronic distribution.

    By now electronic distribution should be the default if an institution has a customer’s email address on file. Printed paper should become a chargeable option.

    Too much emphasis has been placed on the relative security of sending information over digital medium. What is stopping somebody else from opening my letter, or the postman from delivering to the wrong mailbox? How is a signature scribbled on a paper cheque more secure than an electronic transfer authorised after logging in with a username, password and 2FA OTP?

    If you wouldn’t use a cheap lock that has the same key as a thousand other households in your neighbourhood, then you wouldn’t make a password “123456”. If you wouldn’t take a candy from a stranger, then you wouldn’t open that attachment from Amy Yip. Weeding out bad stuff on the Internet seem a bit harder, but in reality it is not much different from everything else in the physical world – especially if made an important part of early childhood education.

    The case for children

    There has been advocacy that children should have little or even no exposure to electronic devices. They need to see, feel and touch paper. They need to learn penmanship.

    No doubt it is good to have children explore the world from different angles, but let’s not kid ourselves (pun intended): our children will live in a future fully surrounded by electronic devices. Not too long ago our parents were once surrounded by print advertisements, smog generating vehicles, hand-drawn cartoons, and washed their clothes by hand. Where have those gone? Do we still carve words on stone?

    Penmanship and writing on paper is already becoming a thing of the past. Just like mechanical watchmaking and oil painting, it will become a form of art.

    Various articles seem to suggest that early exposure to electronic devices can cause ADHD, ADD or even depression. Maybe it does, but is it really the electronic device itself or the games, TikTok and social media? When I was young, I was told not to watch TV all day long. Our parents were probably told not to play marbles all day long. Is YouTube any different?

    Like it or not, all our children will likely grow up interacting with computers – if not as part of their education, then certainly as a large part of their work. Today’s artists are already using digital cameras, Adobe Photoshop, computerised music notation software, GarageBand, and a myriad of other digital tools to supplement their art. Doctors, nurses, and hospitals all depend on computers to be efficient. With the exception of maybe a Shaolin Monk – if that is what you desire.

    Children should gain familiarity with reading, typing, controlling, interacting and understanding how a computer device function. That is not to discount the need to restrict access to TikTok and YouTube, just like how we weren’t supposed to mix with certain groups of friends or have access to certain books or TV channels. The need for parental control hasn’t changed.

    Are we really saving the Earth?

    If the goal is really to save the Earth, removing plastic straws and switching to paper cups aren’t the solution. Corporations should make it a mission to aggressively reduce paper use. Governments should help drive investments into improving bioplastics.

    Of course we still need paper, but we shouldn’t deliberately avoid technology. Writing an essay on a piece of paper should hopefully be a thing of a past, but children should still do art, and I still need to wipe my ass.

    Wait, there’s bidet sprays.

    I hate paper.

  • The end of an era, start of a new

    The end of an era, start of a new

    WhyMobile launched the 3rd major revision of its website earlier this morning. But instead of talking about the new site, this is a little journal to reminisce how far it has come.

    A proof-of-concept site was first built in April 2004. It was nothing more than a static site with an order mailer form that sends an email. The first version launched two months later in June 2004. It was written in PHP 4.

    WhyMobile, therefore, was formally incorporated, and a lot of crazy things happened in the years that followed – including operating an outdoor push-cart in front of Plaza Singapura, to an outlet next to the durian stores in Geylang with “interesting” customers.

    The second version (cover image above) was built circa June 2008. It was written in PHP 5 and deployed as a single CentOS 5 VM. It was nothing fancy – no frameworks, no 3-tier architecture, no design patterns, nothing. Just plain old Apache, PHP, and a local instance of MySQL.

    WhyMobile ran on a Sun Fire X2100 server (2nd from top) as a single Virtual Machine.
    Photo taken Apr 2008.

    The Sun Fire X2100 server where it ran as a VM also had other VMs. The WhyMobile VM was only allocated 512MB of RAM out of the 4GB total on the entire server.

    (Noteworthy mention: The server ran VMware Server 1.0 on CentOS 5 + Software RAID.

    The crummy old Sun server ran and ran and survived a disk failure/upgrade or two, until a time when Cloud services became more efficient and cost-effective. It was eventually wheeled out of the datacenter in August 2014.

    The old Sun server (middle) was still working when it was pulled out.
    Photo taken August 2014.

    So sometime in June 2014, the website moved to DigitalOcean. It ran on a base Ubuntu 14 instance with 1GB of RAM and remained that way for the next 6 years. Minor tweaks and adjustments were made as the business demands changed but never was it upgraded to a newer version of Ubuntu or PHP.

    Sometime between 2010 and 2018, there were also two “mobile” versions. The first version was based on a very early version of iUI, and the second version based also on a very early version of jQuery mobile. The mobile version was meant to be a super lightweight product catalog since the predominant connectivity was only 3G back then.

    “Mobile” version, circa 2011-2016 based on jQuery Mobile.

    But it was all written in PHP 5, and people have given me weird looks.

    “Really? PHP 5? Isn’t PHP slow?”

    No, sir. At its peak, the website was serving around a million page views a month. Remember: it had only 512MB RAM and was sharing it with a MySQL server. It never flinched.

    CPU barely inched past 4% while serving on average of 400k pageviews/mth.
    CPU chart from DigitalOcean, 17th November 2020.

    Remember – no bloatware, no frameworks, no nothing. It is a good reference for KISS.

    Still, I am amused that it ran for 12 years (2008-2020). Time flies.

    But by around 2017 I knew the website wouldn’t last much longer. Not because it wouldn’t continue to run (there were fair concerns on security, the evolving PDPA laws, and all that) but because many competitors had “upgraded” their websites, albeit sloppily, and I have been receiving feedback that the site looks dated.

    I had embarked on several attempts to revamp the website between 2017-2019 but failed. I spent quite a fair bit of time evaluating various PHP frameworks (CI3, Laravel). I was mucking around and having a war with the ORM, and eventually arriving back at square one.

    Building the site has always been a one-man-show. A small business like WhyMobile will never be able to afford the skyrocketing salaries of Software Developers in Singapore. I was essentially paying myself over the years, and I “owe” the business an overdue revamp.

    With kids and a hectic work schedule, the revamp never happened… until 2020.

    2020 came. COVID-19 came. I would be kidding if I said the business wasn’t affected.

    During the Circuit Breaker, it wasn’t too bad. Then the trickle-down effect started to become apparent in Q3 2020.

    Barely any foot traffic in Far East Plaza.
    Photo taken 12th October 2020.

    I knew we had to do something to embrace the new work-from-home, shop-from-home, stay-at-home, die-at-home culture. I bit the bullet, picked a framework, committed to it, and then spent almost every single weekend of my spare time working on the code. Son’s at a class? I’m coding. Son’s taking a nap? I’m coding. Son taking a poop? Coding.

    The launch of version 3 was intended to be past midnight on Monday 16th November 2020, but AWS was giving me grief about getting SES going in production mode.

    It was resolved the next day, and here we are, Tuesday 17th November 2020 at 01:00 hrs.

    Home page of WhyMobile 3.0, launched 17th November 2020.

    And for the record…

    # cat /etc/issue.net 
    Ubuntu 14.04.5 LTS
    
    # php -v
    PHP 5.5.9-1ubuntu4.26 (cli) (built: Sep 17 2018 13:46:30) 
    Copyright (c) 1997-2014 The PHP Group
    Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
        with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
    
    # mysql -V
    mysql  Ver 14.14 Distrib 5.5.62, for debian-linux-gnu (x86_64) using readline 6.3
    
    # uptime
     07:09:19 up 973 days,  8:02,  1 user,  load average: 0.00, 0.01, 0.05
    
    # shutdown -h now
  • Hiring Singaporean Software Engineers

    Hiring Singaporean Software Engineers

    I’ve been hiring Software Engineers over the past few years in Singapore, and I notice a worrying trend.

    As a local business, I always want to hire Singaporeans first; I want to give our own young people a chance; I want to see our local SMEs develop a strong Engineering culture, but recently it has become really difficult.

    One of the reasons could be because good local Software Engineers have gone to apply for Tech Giants, MNCs, banks, GovTech, etc. where they can be paid reasonably well, get good benefits, etc.

    The unfortunate thing is that small businesses and startups receive the lower percentile of the cohort, and that sucks, because these people waltz in and ask for a pretty high salary “because industry standard”.

    Bullshit. The “standard” is based on what you can do, not what others can do.

    I recently put out a job advertisement on LinkedIn, and after about a week, I received around 100 applicants; there were only 3 Singapore/PR, 2 Malaysia, 5 Philippines, 6 Myanmar, 2 China and the rest are from (you probably guessed correctly) — India.

    As a local business, plus recent COVID-19 Government incentives to favour hiring of locals (JSS, JGI), I called up all the Singaporean candidates for interview, but was met with disappointment.

    Note1: All of the candidates whom I describe below (regardless of nationality) are mostly fresh graduates with 1 year or less of work experience.

    Note2: Also, just to be clear, this is not a blog post to diss all Singaporean tech graduates. Frankly most graduates I’ve met from local universities like NUS or NTU are decent. This blog post is targeted at the “COVID-19 cohort” I encountered this year.

    I usually put candidates through a fairly simple technical quiz. It is no where close to the likes of Google and Facebook, but is effective in weeding out candidates that lack basic technical knowledge. There’s no coding; just questions and verbal answers.

    What disappointed me the most was that despite having the upper hand in terms of Government support and language proficiency, Singaporean candidates came out weaker.

    The government has actually done a good job of enticing businesses to hire locals, because they are in effect subsidising the salaries of Singaporeans, and then making foreigners expensive by increasing the salary brackets, and imposing quotas and levies.

    In addition, I like to work with locals because you see, the primary language of Singapore is English. (This is different from our national language Malay, which is purely symbolic.) Singaporean candidates are usually very conversant in English, especially those born after the 1990s. The other nationalities — especially Myanmar or China — are not so lucky; English is not their primary language, but despite their struggles, they picked it up, travelled here, took a course (such as the Graduate Diploma from NUS-ISS, which I interviewed quite a bit of applicants from.)

    I commend the effort of candidates who try their best to explain a concept in a language they aren’t familiar with. I could tell that they knew for example what a particular algorithm is about, but are unable to explain in English. They try their best, and as a recruiter, you can tell if somebody knows their shit or not.

    However Singaporeans who are naturally strong in English tend to lack actual technical understanding of many things, and instead because of their fluency in English, they are able to respond quickly with guesses, a.k.a. “smoke” — sometimes rather intelligent guesses — but that’s not what a recruiter is looking for. We don’t hire you to tikam (guess). We expect you to know your stuff. Of course I don’t expect candidates to know everything, but the fundamentals must exist.

    Sometimes after a candidate answers incorrectly, or maybe tries really hard, or makes really close guesses to the correct answer, I will share the answer and explain why, etc. Some Singaporean candidates I have come across seem nonchalant to the fact that the recruiter had actually taken an effort to explain something, and they simply answer it with a rather monotonous “oh, OK.” The better candidates would usually ask more questions, or show that they had a eureka moment.

    The other trend I noticed is that Singaporeans tend to pick the swanky Degree courses, like Cyber Security. Whilst I have no qualms with somebody taking a keen interest in this area of specialisation, it is quite impossible to learn that in a 1 or 2 year part-time Degree without even having learnt any fundamentals.

    I asked one candidate why did he pursue a Degree course. The answer is exactly what I expected to hear: “A Degree is the minimum now.”

    Let me assure you it is not — at least not in the private sector. I have hired people who have completely irrelevant Degrees but taken a bunch of Udemy courses, taken it upon themselves to work on some personal projects, and proven that they knew their stuff. A Degree makes you expensive (because you would have priced your expectations so) and that actually makes you less employable. I much prefer a candidate who has work experience than a frivolous Degree.

    ~

    So with the benefit of English proficiency, plus not having to deal with the perils of living alone in a foreign country, why do these Singaporean candidates turn out weaker?

    Wrong school/course? Should we stop letting crappy private Degree programmes be taught in Singapore?

    Not paying attention in class? Have they gone through too many years of mundane Singaporean education and grown nonchalant, uninterested and bored?

    Too comfortable? Should we maybe instead yield a higher rate of unemployment so that there’s a pressure to get better?

    I really don’t know leh.