Published Articles

Enter a search term to find articles.

So, I have recently resigned from the company that I work for and started looking for a new one. I sent out my resume to a few interesting senior PHP developer recruitment ads that I saw online and one recruiter scheduled me for an initial interview. The interview went well and I was able to answer all of the questions she asked me. I was also able to ask couple of questions myself. So she scheduled me for a technical exam which she will send the details through the email. Couple of hours later I received the email with the instructions for the technical exam. I was drinking soda while reading the email and I almost choked when I got to this part: > Create the following: > > A web app that does CRUD with authentication and user roles using PHP/Laravel + React.JS. > Create APIs, using PHP/Laravel, that is consumed by your mobile app (React Native, iOS preferably otherwise Android). > Add features that will impress us to showcase your skills, expertise, and experience. Examples below: > > - payment gateway (Paypal, preferably Stripe) > - maps / navigation (Google Maps, Here, etc.) > - social media (SSO, automatic posting, etc.) > - machine learning / AI (facial recognition, eye tracking, etc.) > - blockchain / cryptocurrency > - digital signature, image processing, etc. > - SMS / email integration > - real-time, push notification (chat for example) > - may use any other external or 3rd party API integrations My first thoughts were, *Are they serious?! Are they really asking me to implement Payment Gateway, Navigation, Machine Learning/AI, Blockchain/Cryptocurrency on a freaking technical exam to IMPRESS THEM?!* Dear recruiters, please do not do this. This is equivalent to me applying as a dentist and you're asking me to perform a brain surgery as a technical exam just so I could impress you. This is like asking me to develop a product MVP on my technical exam. This is giving me an impression that you either do not know what you're looking for from a senior developer, or you have no idea what these technologies are. If you have no idea what skillsets to look for from a candidate, then ask some one who has expertise on the field, like other senior developers. And I am 100% sure they will not include Blockchain or Machine Learning from that list.


In this post, I am going to talk about my personal opinion regarding DRY, KISS and YAGNI versus Coding Standards especially when working in a team setting. I understand that you might not agree on some (or maybe even all) of the things that I have written here and I respect that. Everyone is entitled to their own opinion. So I encourage you all my readers, to look at this article with an objective perspective and a broader-than-usual mindset. So with the disclosure out of the way, let me get to the point. Always prioritize DRY, KISS and YAGNI over Coding Standards - even if you are in a team setting. This comes with one condition however, that you need to have a good amount of test coverage so you have confidence in case that you need to refactor your code in the future. **DRY *(Don't Repeat Yourself)*** - means that each small pieces of knowledge (code) may only occur exactly once in the entire system **KISS *(Keep It Simple, Stupid!)*** - means to try to keep each small piece of software simple and unnecessary complexity should be avoided to not incur any technical debt. **YAGNI *(You Ain't Gonna Need It!)*** - means that always implement things when you actually need them and never implement things before you need them. I personally think these principles trump any coding standards a team might implement. And I am willing to go above and beyond that and say **DRY, KISS and YAGNI should be the guiding principles of teams when implementing Coding Standards**. ## Story Time! I have recently started working as a Lead Developer in a team, and one of their Coding Standard is to **always use a FormRequest class** in the controller. So here I am, working on a feature and I have one endpoint that only receives one parameter on the request, which is already covered with written tests. Also, mind you that this request parameter is only used for this endpoint and not anywhere else in the application. ``` public function update(Request $request) { $request->validate(['processed' => 'required|boolean' ]); // Some other process here then return a json response... } ``` Now, I am being told to refactor this into a `FormRequest` class. So I asked, why? Because I honestly don't see the need to. Why do I have to incur additional tech debt by adding a separate class that will only be used for validating a single request attribute? And this piece is not going to be used in any other place,so i'm not violating code duplication. What gives? KISS and YAGNI! ***But we have to follow Coding Standards!*** This is a classic example of letting the developers incur additional techical debt without any benefit at all, just for the sake of Coding Standards. In my most honest opinion, when the code is well-tested, readable and at its simplest form; when it can be easily changed when the need arise, then that is a good code. And I understand the need to be one with the team you are working with, but programming is not a military industry but a creative one. And the possible amount of incurred technical debt when blindly following coding standards far outweighs that argument. And most of the time, that incurred technical debt is never paid. I have seen it multiple times. Also, developers grow when they get to figure out their ways of deciding when to use certain methodologies and tools, and when to keep things simple. That decision can then be guided by the team during a code review session. And again, as long as the code is covered with tests, refactoring should never be a big concern.


As a developer, we often times deal with massive amount of nested relations and multi-dimensional arrays. Which also means from time to time we get hounded by some unexpected `Undefined index` or `Trying to get property of a non-object` errors. For me, I often times experience this when I'm working on generating excel reports. So let me give you some real world (almost) examples.. ## Situation... Let's say we are creating an export excel report functionality for a helpdesk ticketing app. We have a `$ticket` model that has an `id` field. It belongs to an `$approver` model that has a `full_name` field. So when we plot on excel sheet we want to know who is the approver of the ticket. Somewhere in our code we will have something like: ``` // Assume that the array keys are the excel headings.. return [ 'ticket_id' => $ticket->id, 'approver' => $ticket->approver->full_name, ]; ``` At first this looks all good. However, if the **ticket has not yet been approved** `$ticket->approver` will result to `null`. And since you are basically doing `null->full_name` you'll get the really nasty error of `Trying to get property 'full_name' of non-object`. In reality, if `$ticket->approver` is null, we want it to just return `null` so the excel cell can be empty and not worry about any error. ## optional(...) to the rescue!? Yes! The magical `optional(...)` helper function can help here. So we can just say: ``` return [ 'ticket_id' => $ticket->id, 'approver' => optional($ticket->approver)->full_name, ]; ``` This looks quite okay already. You submit a PR and what a productive day it is, right? But then your client decided to add another caveat. Now `$approver` model belongs to a `$company` model that has a `name` field in it, and your client wants that added on the excel sheet too. No problem! ``` return [ 'ticket_id' => $ticket->id, 'approver' => optional($ticket->approver)->full_name, 'approver_company' => optional($ticket->approver)->company->name, ]; ``` However, if for some reason `$company` is not present from the approver model then we'd be back to that nasty error again. Okay so we can just wrap it in another `optional(...)` right? Well, we can do that... but it does not look clean... and there is a better solution. ## Arr::get(...) If you are not yet familiar with what this helper does, take a look at the [official documentation here!]( Let's go ahead and change our implementation: ``` use Illuminate\Support\Arr; ... return [ 'ticket_id' => Arr::get($ticket, 'id'), // Apply here as well so it looks uniform :) 'approver' => Arr::get($ticket, 'approver.full_name'), 'approver_company' => Arr::get($ticket, ''), ]; ``` Now if either `$approver` or `$company` model is not set, we do not have to worry about the nasty error. And it works seamlessly on multi-level nesting too. Note: Obviously, the implementation will not work if the inner relation is a `Collection`. That's a totally different approach when plotting on an excel cell.


Today at work I implemented Parallel Testing to one of our projects. Perfect timing as we also just recently upgraded to Laravel 8 (coming from Laravel 7). I was certain that Parallel Testing is available in Laravel 8 as I followed the development of this feature since the beginning of this year. However, after installing `brianium/paratest` package to our app and running the command `php artisan test --parallel` I encountered this error: ![Parallel Testing Error: Requires Laravel 9]( This got me confused, so I checked the Laravel 8 documentation for Parallel Testing and it was there. []( However, this doesn't solve the issue as nothing in the documentation mentions this error. So I decided to dig a bit further. And as it turns out, Parallel Testing was originally created for Laravel 9 and then backported to Laravel 8. Due to this, earlier versions of `nunomaduro/collision` package (5.0, 5.1, 5.2 - which what I was using at the time) had a restriction to only use `--parallel` option on Laravel 9, but version 5.3 removed that restriction. [This link shows comparison of collison version 5.2 to 5.3.]( Checkout line 74 of `src/Adapters/Laravel/Commands/TestCommand.php` file for the removal of restriction. So I promptly updated `nunomaduro/collision` to `^5.3` on my project and fixed the issue. While at it I also took the liberty of creating a [pull request to laravel documentation]( so that this issue is properly documented and other developers don't waste their time in the future. Peace!


Laravel team has recently announced that they are moving from a 6 month major release cycle to 12 month major release cycle. This is due to many users feeling that versions were being released frequently since adopting the *"semantic versioning"* standard even though the cycle speed stayed the same. And because of this decision, the team decided to backport parallel testing to Laravel 8, which was supposed to be a major feature of the Laravel 9 release. Developers like us can now enjoy the benefits of faster running tests as of Laravel 8.25! We can read the full announcement here: [Laravel: New Release Schedule]( Here's a preview of tests in one of my major projects before and after implementing parallel test. ![]( As you can see, that's about 50% increase in time it took to complete the entire test suite and more than 80% reduction on memory usage. I don't know about you but that is insane! You can read full details of the new feature here [Laravel: Parallel Testing Is Now Available](


I recently updated my dev machine (Macbook Pro) to macOS Big Sur version 11.1. After upgrading, I encountered this error after running `npm run dev` on one of my projects. ![]( Here's a quick fix that worked for me.. Make sure you are using the LTS version of node. You can get it from []( (version 14.15.4 as of this writing). Run `npm rebuild node-sass --force` command. And you should be good to go!


TIL that you do not need the full class name (or the full method name) when filtering tests to run. I was working on some documentations writing today when I ran my tests with a mistyped `User` filter and to my surprise, it loaded and ran all tests with the word `User` on class names and methods. Below is how it looked like after I ran the command (some tests have been redacted).. ``` ➜ p2p git:(develop) ./vendor/bin/phpunit --filter=User PHPUnit 8.5.8 by Sebastian Bergmann and contributors. Batch Import Job (Tests\Unit\BatchImportJob) ✔ It belongs to a user Company (Tests\Unit\Company) ✔ It belongs to many users Contract (Tests\Unit\Contract) ✔ It belongs to many users Media Security Check (Tests\Unit\MediaSecurityCheck) ✔ It belongs to a user User Setting (Tests\Unit\UserSetting) ✔ It belongs to a supervisor ✔ It belongs to a user ✔ It belongs to a delegate Companies Deactivation (Tests\Feature\Admin\CompaniesDeactivation) ✔ Deactivating a company also deactivates its users User Change Password (Tests\Feature\Admin\UserChangePassword) ✔ Can change password of a user ✔ Can resend email password reset to user User Contracts (Tests\Feature\Admin\UserContracts) ✔ Can attach a contract to a user User Deactivations (Tests\Feature\Admin\UserDeactivations) ✔ Can deactivate a user ✔ Deactivated users cannot login ✔ Can reactivate a user User Export (Tests\Feature\Admin\UserExport) ✔ Can export users User Settings (Tests\Feature\Admin\UserSettings) ✔ Can update user settings Users (Tests\Feature\Client\Users) ✔ Can list all users ✔ Can get user details ✔ Can only get details of users in the same company User Filters (Tests\Feature\Filters\UserFilters) ✔ It can load user companies ✔ It can be filtered by company association User Picklists (Tests\Feature\Supplier\UserPicklists) ✔ Can update picklist Users (Tests\Feature\Supplier\Users) ✔ Can list all users [Some tests have been redacted] Time: 44.64 seconds, Memory: 86.50 MB OK (83 tests, 204 assertions) ```

Marvin Quezon · Copyright © 2023 · Privacy · Sitemap