A few months ago, Mohammed joined our Clarabridge Engage development team for an internship and he has since then become one of our full team members. This blog post is about his story and how HackYourFuture.be helped him find a place in our company, the technology industry of Gent, and ultimately Belgium.

“Three years ago I decided to leave my homeland, after an exhausting period of war, destruction and loss. I left my family hoping to improve my future and achieve my ambition. Belgium was my destination and by now I’m pretty sure that it was the right choice. When I got the Belgian residence I started to search for a job based on my resume in Palestine. I had graduated from the 'Information and Technology department' in Gaza, but I knew that I needed more experience and knowledge if I wanted to make it work here.” - Mohammed

My Experience at HackYourFuture

In his search for more education and building more experience, Mohammed was helped by the VDAB, Flanders’ public employment service. They suggested he attend the HackYourFuture course. HackYourFuture was founded in 2015 in Amsterdam, with the aim to enable refugees to build digital skills for a career in web development, facilitate the integration of newcomers, and address the shortage of qualified workforce in the IT sector, a shortage reflected by the amount of open positions we have here at Clarabridge.
In May 2018, HackYourFuture Belgium launched its first class in Belgium with 13 highly motivated students, Mohammed being one of them.

Mohammed recalls the course was a perfect match for him for several reasons:

“The course covered programming languages with interesting modules (CSS, HTML, JavaScript, Node.js, React). Each of the modules are taught by volunteer coaches with experience in the field of programming.“
“Because the courses were given on Sundays, it allowed me extra spare time to continue my Dutch lessons and driving lessons. And although I’m learning Dutch, the fact that the lessons were taught in English helped me too.”

The first class of HackYourFuture Belgium
The first class of HackYourFuture Belgium

During 6 months the students followed these lessons and for the last 9 weeks they worked on a project together in smaller groups.

“The coaches of HackYourFuture were as excited as we were, because for most of them it was their first time teaching. During the week, when we studied and worked on our assignments, they were always available through Slack to answer our questions.

When asked about what makes the HackYourFuture bootcamp stand out from following any of the online courses plentifully available through the internet, Mohammed points to the team aspect:

“By the final project we worked in groups of three, and every Sunday we divided the work between us. During the week we also kept in touch, and often we could use the HackYourFuture offices to work on the project.”

Mohammed’s project involved making a website for an institution from Brussels that would help homeless people and refugees to find the right information and help more easily. At the end of the course each team presented that project. At this graduation event one of our Clarabridge team members was also present.
Of course, for the students, it now became real. Mohammed: “We were worried about the next step, which would either be an internship or a job.” HackYourFuture assigned each student a mentor that would help the student take that next step.

Mohammed at the graduation
Mohammed at the graduation

Starting the internship at Clarabridge

This was the time when our company came into view for Mohammed. After having seen the projects at the HackYourFuture graduation event, we were impressed how far they got in only 9 weeks. We invited Mohammed for an interview, and his dedication immediately struck us. He explained what he was able to build, and what he learned at the HackYourFuture course, and this for us was the main deciding factor for offering an internship.

“I was lucky to get a four month internship at Clarabridge in Ghent, Belgium. I have learned new things every day, being surrounded by experienced and talented developers and engineers who are very helpful and very patient. They didn’t seem to get bored of my hundreds of questions.”

When an intern joins our team, we first of all look for the right project to work on. The ideal project is typically a stand-alone new feature (so the scope of it is clearly defined), challenging enough (from a technical and product perspective), should have as less external factors as possible (so there’s as little roadblocks as possible), involves enough existing components of the codebase (to evaluate how easy a person finds their way), and most importantly: a project that results in something that we can take into production and is visual to our clients and team. Having that success experience of having your code shipped into production is something we always strive for.

Mohammed started his work on an importer-system that would allow our customers to upload an Excel file with a list of account related settings. The feature would mean a huge time-saver for customers who want to configure several canned responses, tags, or saved filters at once.
Mohammed was assigned a specific mentor in our team as well (who helped on an almost daily basis), but the whole team got involved in reviewing parts of Mohammed’s code.

Mohammed’s first major Pull Request
Mohammed’s first major Pull Request

What I learned

Four months later, when this and several other projects of Mohammed's have been taken into production, we asked Mohammed what some of his main takeaways since his start in our team are:

  • 🏠 “When I started at Clarabridge, my main worry was that I had never written a line of PHP code in my life. I was wondering how I’d be able to get the hang of a complete language in only a couple of months. But actually, I quickly realised that learning PHP was the least of my concerns. Instead, my mentor and I focused a lot on how to write code using the principles of S.O.L.I.D. I probably learned more about programming trying to structure my code this way, than learning about language syntax.”

  • ✂️ “I always had to keep in mind that I was writing code for others. At some point in the future, another developer in the team will work on what I wrote, so I had to think wider and wiser, and take future uses and possibilities of my code into account. I refactored my code several times because of this.”

  • 🔨 “It’s sometimes tempting to fix an issue by writing code around it, but I realised that often this just causes a new issue. I try to to take more time to solve the problem at its root.”

  • 📚 “When I started my internship, I read the blog posts on this Clarabridge Developers Blog. Unfortunately, I had a hard time understanding some of the content. A month later, I re-read them and could already understand more. Until this day, I keep reading the posts which didn’t make sense at that time. Being part of an ambitious team who reads a lot, encouraged me to learn and read more too.”

  • 👯 “It’s often a balance between trying to find the answer on your own, and avoiding to be stuck for too long, and eventually asking for help. Time is valuable.
    I started to trust my teammates’ opinions, and worked on giving them a reason to trust me back. I learnt to avoid saying “I can do it alone” or “It is a piece of cake”. Instead I said “I’ll try to do it but I may need your help”. The team loves to help each other; so if you need help, just say it. When getting help from others, my teammates often had other personal perspectives. I learned to accept that, and picked from those that suited me. Eventually, by experience, you will have your own perspective.”

  • 👾 “Never underestimate another programmer, even if you know that you have more experience than him; always try to listen, discuss and understand. During the summer holidays, a talented 18 year old student joined our team. He didn’t know a lot about our application, but in a very short period of time he implemented more than 12 small improvements to the product. The whole team was impressed by what he has done. Because the improvements he worked on were smaller, easy to understand projects, I also learned from him by reviewing and checking his Pull Requests.”

That the most important lessons Mohammed lists are mainly about communication and how to learn from others, and the impact of that on how your code is structured, really show he’s become an integral part of our development team. It’s also a testament to the way a product is always built by a team of people (and not a single 10x engineer). So it’s no surprise that the project Mohammed is currently helping to build is one of our most requested features.

What is next, and how can you help?

“For me, HackYourFuture was my starting point. I was invited to be an assistant coach in the upcoming course - now at its fourth edition already. For me this is a great opportunity to pay back some of their generosity, and of course to continue learning.” - Mohammed

Know that HackYourFuture is run by volunteers. They are always on the lookout for people who work with challenging technologies in innovative companies. If you feel like sharing some of your knowledge with the students, maybe think about becoming a coach?
Helping as a coach can mean giving a few lessons, but also just being around when the students do their work, and trying to help out where possible.
Know that HackYourFuture is not only about programming, it’s also a real community supporting and helping each other to start a new career in Belgium.

HackYourFuture Coaches
HackYourFuture Coaches

If you’re a company interested in hiring some of the graduates, we hope Mohammed’s story helps. We can attest that the students are trained to perform well as junior web developers in a modern IT team, write clean code, and think like problem solvers. From this experience we especially remember the student’s eagerness to learn and start a development career.

Mohammed thanks

“Clarabridge is my home now, so one of my responsibilities is to make it bigger and keep it safe and shining.
With this post, I also want to thank everyone who helped me through my journey, by encouraging words or advice, or even a smile.
Thanks HackYourFuture and all of the coaches who showed the way for us, especially Frederik De Bleser who believed in me and kept giving me advice even after the course.
Thanks to my mentors at Clarabridge: Anthony, Toon and Cedric. And the other teammates who didn’t hesitate when I asked for help: Jenne, Gheerwijn, Thibaut, Thomas, Jared, Jasper, Hans and Erik. And thanks to Jurriaan who gave me the opportunity to be one of his team members, and for being a human before being a team leader.”

Want to join the course, or do an internship too?

If you feel like joining a HackYourFuture course, know they always accept applications. (The 6th course is starting in a few days!)
And of course, we also invite recent graduates or others interested in doing an internship in our team, to contact us.

Tags: People Internship Team

People receiving code reviews from me on a regular basis will know this by now, but if I see inheritance happening in new code, I get moody. I look the extends in the eye and prepare for battle. I pick up my SOLID axe and start examining the principle that will allow me to slay this sub-class beast. And then I cry a little because I'll have to explain again where this centuries-old grudge comes from.

Now, don't get me wrong. I do understand the usefulness of inheritance in very specific cases. But most of the time when I encounter a subclassed beast during a code review I go all out offensive on it. Let's explore why:

Single Responsibility Principle

If you've been Object Oriented Programming for some time and you've been looking around a bit, you've definitely encountered the SOLID principles. These are basically principles (not rules) that, when followed, will help you produce code that's easier to comprehend, change and test than when you were not following them. The first principle is the Single Responsibility Principle, which states that a class should have only one responsibility, or "one reason for change".

Let's try and use that to mitigate this case of inheritance:

interface Users
{
    public function getById(UserId $id): User;
}

class UsersDB implements Users
{
    protected $db;

    public function __construct(DB $db)
    {
        $this->db = $db;
    }

    public function getById(UserId $id): User
    {
        // ...
    }
}

class UsersCached extends UsersDB
{
    protected $cache;

    public function __construct(Cache $cache, DB $db)
    {
        parent::__construct($db);

        $this->cache = $cache;
    }

    public function getById(UserId $id): User
    {
        // get from cache?

        // if not in cache
        $user = parent::getById($id);

        // put in cache

        return $user;
    }
}

Apart from all other issues that we have here, let's try to find out if the Single Responsibility Principle holds for this implementation. Looking at the class UsersDB, we can clearly see that it has just one responsibility: it represents a bunch of Users that are persisted to our database. It has no other reasons to change than for the purpose of representing users persisted in our database.

Now let's look at the UsersCached implementation. It represents a bunch of Users as well, in this case it caches them. We could think that this class has only one responsibility, until we see the parent::getById() call. It basically calls a method that we inherited (so it's available in our class) from the parent class. The knowledge needed to query the database is actually in our class because of the inheritance!

You could argue that it's still ok since it's clearly a parent class and nothing's wrong there, but let's look at it through the lense of a class should have only one reason for change. What if we decide that the constructor of the UsersDB class will now take a PDO instance instead of our own DB class? Guess what! The implementation of our UsersCached needs to change as well, because it needs to pass the PDO instance on to its parent. So a decision about the database made us change the caching class. And it's obvious that changing the caching mechanism would also affect the caching class. Which gives us more than one reason for change of this class.

This is clearly a violation of the Single Responsibility Principle.

We could fix this e.g. by using the Decorator Pattern:

interface Users
{
    public function getById(UserId $id): User;
}

final class UsersDB implements Users
{
    private $db;

    public function __construct(DB $db)
    {
        $this->db = $db;
    }

    public function getById(UserId $id): User
    {
        // ...
    }
}

final class UsersCached implements Users
{
    private $users;
    private $cache;

    public function __construct(Users $users, Cache $cache)
    {
        $this->users = $users;
        $this->cache = $cache;
    }

    public function getById(UserId $id): User
    {
        // get from cache?

        // if not in cache, get from nested user object
        $user = $this->users->getById($id);

        // put in cache

        return $user;
    }
}

As you can see, it's only a very small change.

  • we added final keywords to our classes and private to our variables to indicate that we don't want inheritance to happen 😏
  • we made both classes implement the Users interface
  • we injected an implementation of the Users interface into the constructor of the UsersCached, which will be called when no user is found in the cache.

You could try and argue that this is no better because we still rely on the Users interface to stay stable. But if that interface changes, the responsibility "representing a bunch of users" changes, which is exactly the one responsibility that we have for our class. Changing the implementation of our UsersDB class will not affect the UsersCached class anymore, except when the contract of the interface is broken. Great!

Dependency Inversion Principle

Let's take a short second look at the same code examples from above, now while trying to look at it from another one of the SOLID principles, the Dependency Inversion Principle. The principle comes down to depending on abstractions instead of concretions. In the case of the first example, the UsersCached extends UsersDB, which it needs when there's nothing found in the cache. We depend on a concrete class, which is a violation of the principle. In the second example, we made UsersCached implement the interface directly instead of extending from UsersDB. We then inject another implementation of Users in the constructor of UsersCached. Since we depend on the interface here, we don't depend on a concrete class anymore, and any implementation of the Users interface should work! This solution follows the principle! An added benifit of this is that our UsersCached instance is now much easier to test: we just need to inject a fake Users interface and see if it gets called when the cache doesn't have the value that we look for.

You could do the same with the other SOLID principles really, take e.g. Liskov Substitution Principle. If a class extends from our class, it can easily overwrite a method to behave completely differently than what it was, so the principle doesn't hold. Again, it's easy to make a violation there.

Shared Dependencies

Now that we have a few SOLID reasons to say that inheritance is not a desirable solution for our problems, let's look at some other ways that I think it is misused. Consider this example:

abstract class Notification
{
    protected $id;

    public function __construct(Id $id)
    {
        $this->id = $id;
    }

    public function toUrl($relative = true): string
    {
        $path = "/notifications/{$this->id}";

        if ($relative === true) {
            return $path;
        } else {
            return "https://domain.of.application{$path}";
        }
    }
}

I see this kind abstract classes quite often. It's a form of deduplication (people think they shouldn't repeat code), but what's problematic is the fact that you won't always know what kinds of exceptions to the rule there are going to be. Consider a class AccountSpecificNotification which extends from Notification. It wants to overwrite the toUrl() method, because account specific notifications are at /account/{accountId}/notifications/{notificationId}. Trouble is, we have to again implement the absolute and relative paths rule, and the chance of making mistakes becomes higher. Also the absolute URL of our domain is now in two classes. The knowledge about converting a notification to a URL is also in two classes. If we have a few of these exceptions, stuff gets difficult to keep track of.

As a solution, you could just make this class an interface and specify the toUrl() method on Notification instances. This way you always know the implementation for a certain type of Notification will be in the class itself. Then you'll have to live with the duplication. This is personally how I often do it. I duplicate stuff when in doubt and refactor later, with the benefit of hindsight.

Another thing that you could do is look at the toUrl() method, and see that it's in fact a shared dependency between Notifications with another responsibility than "representing a notification". It could become another class. Let's write a separate class for it:

final class NotificationToUrl
{
    public function getRelativeUrlForNotification(Notification $notification): string
    {
        $url = '/notifications/' . $notification->getId();

        if ($notification instanceof AccountSpecificNotification) {
            $url = '/account/' . $notification->getAccountId();
            $url .= '/notifications/' . $notification->getId();
        }

        return $url;
    }

    public function getFullUrlForNotification(Notification $notification): string
    {
        $path = $this->getRelativeUrlForNotification($notification);

        return "https://domain.of.application{$path}";
    }
}

Of course this is not perfect either, but it's at least a bit better from some standpoints: we get all the knowledge of converting notifications to URLs in one place, and we don't need inheritance!

In short

If you're using inheritance to fix a problem, I propose that you take a second and ask yourself why. In this post I propose a few ways of looking at inheritance that could help you come to a better solution in some cases.

  • Are you violating one of the SOLID principles? Try and look for a solution where you can adhere to them more.
  • Are you trying to remove duplication? Try to postpone your decisions about the abstraction that you're going to use to remove the duplication.
  • Do you have a shared method that multiple classes need? Try extracting it to a separate class.

Since most of the time one of these methods produces a result that I find more desirable as explained in this post, I'll mostly oppose strongly against the use of inheritance when it's not strictly needed.

Hope that you'll be with me on slaying this beast! Until next time, happy programming! 🐲

Tags: PHP Inheritance Development OOP SOLID

You've made it to this post thinking "Why do we still need to talk about Exceptions?". Well, they're used everywhere in OOP codebases, but sometimes they're used in a way that make debugging a bit difficult. Let's look at some ways to make debugging exceptions a bit more fun!

You know that feeling when you're trying to investigate an Exception that was thrown, but you can't seem to find the origin of it? You dig a bit deeper and you find that it's an exception that was caught and not rethrown, e.g.:

try {
    $this->doSomeImportantStuffWith($foo);
} catch (VeryDescriptiveException $e) {
    // do some stuff here

    throw new SomethingWentWrongException('oh no!');
}

Now, when you encounter this SomethingWentWrongException, you'll see that the trace takes you back to the 6th line of this code example. All information that was inside the VeryDescriptiveException, including its message, stack trace and other useful information is gone. Of course, debugging that error in doSomeImportantStuffWith() would be much easier if you had all that info.

Fatal error: Uncaught SomethingWentWrongException: oh no! in test.php:6
Stack trace:
#0 /Users/toon/Projects/devblog/test.php(34): Test->withoutPrevious()
#1 {main}
  thrown in /Users/toon/Projects/devblog/test.php on line 6

Prevent information loss by using $previous

The obvious answer to this simplified example would be to just rethrow the VeryDescriptiveException instead of throwing a more general SomethingWentWrongException... And that would be valid, but let's say we're implementing an Interface that prescribes that we only throw SomethingWentWrongExceptions. We can't let the VeryDescriptiveException through or we'll break the Liskov Substitution Principle. We want to throw that specific SomethingWentWrongException, while still somehow preserving the information of that previous exception that we caught. Let's check the docs:

PHP Docs for the Exception Constructor

That Throwable $previous = null is what we're looking for! I've almost never seen this being used in the wild, but it's great for our usecase:

try {
    $this->doSomeImportantStuffWith($foo);
} catch (VeryDescriptiveException $e) {
    // do some stuff here

    throw new SomethingWentWrongException('oh no!', 0, $e);
}

this results in this error:

Fatal error: Uncaught VeryDescriptiveException: hello there! in test.php:15
Stack trace:
#0 /Users/toon/Projects/devblog/test.php(23): Test->doSomeImportantStuffWith('test')
#1 /Users/toon/Projects/devblog/test.php(34): Test->withPrevious()
#2 {main}

Next SomethingWentWrongException: oh no! in test.php:6
Stack trace:
#0 /Users/toon/Projects/devblog/test.php(34): Test->withPrevious()
#1 {main}
  thrown in /Users/toon/Projects/devblog/test.php on line 6

As you can see, the stack trace of the original exception along with the one we wrapped it in are presented to us on error! We can see the message as well, and we can even add our own properties to the exception and be presented with them here if we just implement the __toString() method of the exception.

Custom properties in exceptions

Let's say we've been building an API client that does some HTTP requests to an endpoint. Something can go wrong during the HTTP request, and we want to thrown an ApiConnectionFailed exception whenever the HTTP response code is not 2xx or something else fails, so that the rest of our application has one single Exception it needs to prepare for. It would be very handy to debug if that exception contained our HTTP Request & Response objects, e.g.:

final class ApiConnectionFailed extends Exception
{
    private $request;
    private $response;

    public static function withHttpRequestAndResponse(
        $message,
        Request $request = null,
        Response $response = null,
        Throwable $previous = null
    ) {
        $exception = new static($message, 0, $previous);
        $exception->request = $request;
        $exception->response = $response;

        return $exception;
    }

    public function __toString()
    {
        $string = parent::__toString();
        $string .= "\n{$this->request}";
        $string .= "\n{$this->response}";

        return $string;
    }
}

As you can see, we used a named constructor withHttpRequestAndResponse to be able to keep the default constructor for Exceptions, but to also be able to construct it using a lot of extra relevant debugging information. This means that this Exception behaves like other exceptions and is very transparent to other developers.

If something fails, we'll construct the exception like this:

try {
    $response = $httpClient->execute($request);
} catch (HttpClientException $e) {
    throw ApiConnectionFailed::withHttpRequestAndResponse(
        'Http connection could not be established',
        $request,
        null,
        $e
    );
}

if ($response->getResponseCode() === 500) {
    throw ApiConnectionFailed::withHttpRequestAndResponse(
        'We got a 500 error from the host',
        $request,
        $response
    );
}

The exception will always contain all relevant information to be able to debug.

Recap

To quickly recap, you can make your life a lot easier by

  • providing exceptions with descriptive names
  • providing the $previous exception when rethrowing
  • providing all relevant data to an exception
  • providing named constructors for your exceptions to be able to add debugging info but keep the original constructor

Hope that helps! Until next time, have fun coding! 🖖

Tags: PHP Exceptions Development OOP Debugging