I want to show some of what I did in my workplace in the past few months (…April 2021, still technically few months) and since my workplace doesn’t have engineering blog, I want to show it off here.
I’m currently working as a Maintenance Manager at PT DNArtworks Indonesia. I generally helps our client to keep their sites up and running, and manage engineers to work on client’s requests.
In this blog, I’m going to tell more on one of our Admin Panel iteration journey.
Our Admin Panel are originally made by my Tech Director and how we usually use it are by copying it over to another project whenever we need them. At first this pose no problems, the dashboard works as expected and we usually just tell other engineers to copy it from certain projects and call it a day. We can do that because our use case fits perfectly with the original Admin Panel. Most of our sites doesn’t really require super weird implementations, or crazy graph and summary tables, or any super interactive user features — though, when they do, we can just customize the code base directly.
When there’s influx of requests and projects coming in, a lot of problems starts to bugging us. Copying to another project is no longer scalable and very prone to human error!
Problems
Hard-to-find Vanilla Code
The main problem of copying it over and over is: it is hard to find the original one that have the most less-modified code base and not all of us remember the project that hosts the early version of Admin Panel.
A lot of existing projects have their Admin Panel code base modified and updated because of client’s request or simply because our engineers need them to ease their work to update and see the site contents. For example, one of our client’s site have Instagram Post embedded in their profile. This means we need to somehow make the Admin Panel support three-legged OAuth specifically for Instagram (…and Facebook) ????
Tooooo Much Files That Need to be Copied
Admin panel generally have a lot of components that need to be present to accommodate column types the website use. For example, admin panel need to support…. date time picker, WYSIWYG Editor (essentially a rich-text editor), file upload, auto-slug, and etc. Fun, right?
So, just to give you some visualization, things that we need to copy to other projects are…. original code base (controller, views, model, authentication module/connector, helpers), its JavaScript and CSSes, and now we need to copy those dependencies too. Not to mention if the Admin Panel requires special package(s), i.e Logger.
Oh, also, just imagine when we need to update one of those components 🙂 Do you want to think about how we should deliver the patch when we need them in another project? :DDD
Too Much of Mini Configuration that Need to be Edited
Our Admin Panel can be branded, can have their CSS styled and etc., and this takes time if you want to salvage the panel from the project that heavily modified. Essentially what you’re doing is purifying your holy water for your priest. It takes time, energy and effort to make it as vanilla as it can get, then taints them again with code to fulfill client’s requirements, and you repeat it for the next project over and over again ????
Solution
Initially when I got presented with those problems, my mind goes right to “let’s make it as a package. We can zip all of those, and somehow make it portable enough that we can install it nicely via composer and integrate beautifully with CodeIgniter.” but of course we need to think and analyze on how exactly we deliver that as a solution because packing it as a package without thinking its impacts will start a whole new problems and actually discourage our team to use the package.
Main Requirements
Based on problems I described earlier, I think our general theme here are Developer Experience. I mean, most of these problems aren’t affecting any of our exiting users, they might see little change on how to access the Admin Panel, but all the exiting contents (pages on indexer, new, edit and delete items) are still the same. The thing I want to solve is how developers can be more productive by decreasing their burden upon working on Admin Panel.
So here are my key requirements for the solutions I made:
Make it as vanilla as it can get
Just running the usual stuff we do to every project here, as I mentioned earlier. The only difference are we’re making it extra clean because this Admin Panel will be distributed for most (or even for every) projects we made. This will make the Admin Panel as light as possible. Small project that contains only several pages and minuscule of codes will have the same Admin Panel requirements just like most medium sized projects. Lower cost on hosting, right?
Must be easy to setup
Back when this solution was being made, we don’t have any boilerplate for our projects (now we have!), so this part of requirements will solve the “Too much —” problems.
Packaging this to Composer/Packagist package actually solve this issue. All we need is executing composer require groupname/projectname
and tada, its done! ????
Incidentally, CodeIgniter 4—the framework we use, have auto discovery feature. So this helps a lot on making the DX better, meaning no need weird and convoluted configurations after package installation.
Easy to update
Just like any apps, they usually have bugs. One of our pet peeves are hearing from other developers reporting “Hey, we found x bug in the Admin Panel, you might want to update yours too” and you know it is going to be sucks because syncing both code base requires some times and patience. The DX on this are always as irritating as it gets. So we have to make sure updating things wont break existing project—it will be costly to suddenly migrate all of them then when we need to.
If it’s easy to setup, we theoretically can just re-copy all the files to update the code base, but because we’re going to make it as a package, we can just composer update
away the project, and composer will happily update the Admin Panel for you :D. Cost to maintain decreases!
Additional Requirements
Of course after those key requirements, we need to make sure we don’t introduce an even bigger problem than what we already have, especially with developing code that being used in a lot of projects. So while developing and publishing things, we need to take a lot of care on:
Backward compatibility
Just like any package, when defining a new version they need to check if previous version will be compatible with this soon-to-be-released package, but for this specific occasion, we need to make a conscious decision on introducing breaking changes. Is it really needed? Can we make a little workaround so the breaking changes wont happen? etc.
So when making decision on introducing those, we need to think about these factors:
First, lower maintenance cost. Remember our pet peeves we said earlier? If maintenance cost is big, we’re basically busy with maintaining our “favorite” child for every update/upgrade. Of course by “favorite” I meant fussy.
Second, lower the entry of migration from old old code base. While this package is in development, most of our project still uses the old code base of Admin Panel. I made sure that they can just run composer req
, so that every developer in our team feels more incentivized on moving to Admin Panel in package version. Other use case is, migrating the code base from CodeIgniter 3 to CodeIgniter 4. We can just copy-paste the Admin Panel configuration now and it will just work out of the box.
Ranged PHP support
Not all of our clients uses our hosting service, some of them actually have their own hosting, or their organization have certain policy or obeying policies from authorities. This mean not all of our fleets run under the same PHP version. This is problematic because PHP always get updated and not all things can just be migrated.
So Admin Panel need to support at least reasonable PHP version range to allow the developer migrate their project to use newer PHP version or infra team to update the PHP Version in the machine.
Implementations
The first step is Vanilla-ize the code base and make sure things clean as f. We find a project that doesn’t really need to modify the Admin Panel so we can transform them to Admin Panel, then we check for the modified parts and bits. This will make sure maintaining the code base on the Admin Panel be more predictable and easier (since modified parts are just skipping things here and there).
Next we upgrade the code base to fully support CodeIgniter 4. Fortunately one of my coworker’s teammate have converted most of the code base so it run in CodeIgniter 4, the original code base was from CodeIgniter 3 btw). So all what i need is to make it a little bit more tidy.
While upgrading I’m working on the next quest too: make it much more configurable by making use of CI4’s API. Originally this step is kinda hard because this is my first time making a package for CI4 and use their API pretty heavily. The thing is, if we didn’t use their API, we can’t just load the configuration. We need to somehow make a new controller and make a binder from project to the package—bad DX!
Then then then! Data stuffs. Accessing Admin Panel should pass the authentication, right? …so storing authentication data is also important…right? And since our Admin Panel and the authentication part is highly coupled, I decided that we ship the package with user login too. Tough the projects may modify them a little bit, but sure we need to store them in database. So I take a look on what the typical use of our existing projects and somehow make a standarized table out of there…. and I did! So all I need to do is make a new migration class, and making sure it is reliable enough for most of our cases.
Continuing the relay, we need a way of how to publish this package securely, privately, and most importantly: easily. GitLab fortunately have Private Packagist feature built-in. I just need to configure the CI/CD to call GitLab’s API to let them know we have another release. So the publishing job is basically done.
Things to Watch On
Of course packing the Admin Panel as a solution have their own pros and cons. In this part, I’ll explain what our team need to watch on to maintain this package.
First, before publish new release, the new version will need to be tested thoroughly. Since the package is used in many projects, we need to make sure the developer can just composer update
away to update the Admin Panel. If we ship broken things, the developer then need to revert back to previous version and this increase a friction for DX.
Secondly, because the approach is not to touch files in vendor
folder on the project’s repository (Admin Panel package will be copied there by Composer, if you’re not aware of that), we need to add a way of supplying the configurations and somehow make it extensible. Packing the Admin Panel as a package means its code base should not be edited on each project. This will lead to developers have limited access on how to add more functionality to the dashboard to fulfill client needs. So when adding functionality(s), we need to somehow add a way for developer to add custom settings to that.
Third! Releasing new features need to think for generic use case, this means we need to make sure that shipping new features wont affect projects that doesn’t really need them. For example, Client A wants a dedicated page in Admin Panel so that they can connect to their social media and let the site can sync content from their social media timeline, to the site. This functionality only used for this specific project only. So shipping this functionality to Admin Panel as a built-in feature, is not reasonable due to very specific use case being shipped for general use.
Fourth, updating existing functionality will requires extra knowledge on how this specific function being used. This means we cannot just update the implementations, because it will break stuff. This is related with the first Things to Watch On I mentioned earlier, tough fortunately our Admin Panel isn’t that complex yet.
Conclusion
My teammates’ saga of hunting and cleaning Admin Panel is now gone. Our team now can just install it as a normal Composer/Packagist package, no need to clean them. While on it, we also starting to standarize several things, such as our “authentication” table by consulting on most pattern used in our already-existing projects, taking into account on how each of them can start using the package and extend from it.
In short, here’s our old and new development flow when the engineer being tasked on “Install Admin Panel”: