Stop writing the same code. Generate it.

Alex Shevchenko
5 min readJan 31, 2022

--

For more than a half of my life, I’ve been working in the software outsourcing field as an engineer and as a manager. And more than half of that time, I was frustrated by the amount of duplication in programmers’ work. The same or similar code is repeatedly written in different projects and within the projects themselves again and again. This is true for huge enterprise projects with 100+ programmers working on them as well as for small projects with one or two people.

Programmers create automation for very complex businesses and processes but experience the lack of automation in our own work, as we keep writing the same code for authentication and authorization, CRUD actions, UI controls, and so on, and so on.

Of course, our frameworks and tools evolve every day, yet we still need to do much more.

The demand for writing less code is clear: no-code/low-code are trending buzzwords, and the market for such platforms is growing. Personally, I don’t think that the no-code approach poses an answer to the ultimate question of software development, but I like the low-code, since code only need be written for custom business logic.

Thus, as soon as I got some free time after quitting my full-time job, I decided to try to prove the concept I’ve been mulling over for quite a long time, of which the goal is to reduce the time spent on developing web application backend projects with PHP.

In this article, I’d like to introduce and validate Jinn, the code generator for PHP frameworks.

I’d be grateful for any feedback, comments, and suggestions, as I’d like to find out whether the community would find Jinn helpful and, if so, how it should evolve. Or perhaps, you’ll just point out that this is yet another duplicate work? 

What is Jinn?

Jinn is a dev-time tool that can generate models, migrations, view models, authorization policies, and CRUD APIs. Admin panel generation is also planned.

Sample of Jinn definition YAML for a simple Blog application

Why Jinn?

Jinn solves several tasks, but I’d like to describe one that was always a pain in the ass for me and that is, probably, the main reason why Jinn appeared.

Let’s consider a simple backend for a blog-like application that has an API and an admin panel. A new task raised from the business requires adding a string property called category into our post entity. This property can be freely set via API when a post is created or updated and also can be managed via the admin panel.

Solving this task in Laravel will require the following steps:

  1. Use CLI to create an empty DB migration
  2. Write migration code
  3. Run migrations
  4. If you want your code completion to recognize the new field, you have to edit your model
  5. If your project is not a trivial one, you are using API Resources, so you have to update one or several resources to include the new field in the response
  6. Similarly, you probably have a Request class or classes for your create and update API calls, so you have to update those as well
  7. Lastly, you need to update a list and a form in your admin panel, which is another one or two files

7 steps in total: you edited at least 5 files and ran 2 CLI commands.

Now, let’s look at Symfony:

  1. Symfony models are more complex, but luckily you can use CLI to add a field to the model
  2. Also, Symfony is able to generate a migration for you via another CLI command
  3. The third CLI command is needed to execute the migration (why in the hell there are no option to run these three steps at once?)
  4. Most likely you are using the JsonSerializable interface, so you would still need to go and edit the jsonSerialize method in your model file
  5. The last step depends on the way you implemented your API, but anyway, you’ll have to edit at least one or two files to add the new field into update and create methods
  6. Same as in with Laravel, the last step is to update your admin panel

6 steps in total: a least 3 files and 3 CLI commands

Of course, there are solutions for both frameworks which simplify some of the tasks listed above. But Jinn is trying to simplify it all at once. So how this task is solved with Jinn?

  1. Add one line in your definition file
  2. Ask Jinn to regenerate the files via a simple console command.

That’s it. Jinn will update your model, views, controllers, and the admin panel code. It will then create and execute the migration.

Key Concepts

My goal when designing Jinn was to solve a pain point without introducing new one, which would appear if you hit the walls of limitation. This is why Jinn is based on the following requirements:

  • Allow free extension and customization of the generated code
  • At the same time, allow using Jinn to update the generated code when requirements change without losing your customizations

A tradeoff that I decided to take is that Jinn can be used for new models only. It cannot pick up existing models in your project.

Thus, Jinn’s design is based on the following concepts.

Code Generation

Jinn is firstly a code generator and not a framework or library because it provides several advantages considering the requirements set above.

The generated code is simple and easy to inspect since:

  • Only the code needed is generated, i.e., if you don’t need an update method in your API, it will not be generated at all.
  • It does not have to be very generic: specific code can be generated for each entity.

The generated code is accessible because it is generated on dev time and not on runtime (like Symfony’s cache).

These advantages facilitate the extension and customization of the generated code.

At the same time, as Jinn does not introduce any runtime dependencies into your project, you can stop using it any time without losing your generated code and extension work.

Base Classes

Each class generated by Jinn (except for Migrations) is split into two files:

  1. An empty class under your sources folder which extends a
  2. Base class, located in a separate folder which contains all the logic

The idea is borrowed from Propel, a well-known in the past PHP ORM. The main class is generated only once and never updated, so you can use it to customize generated logic freely. At the same Jinn can update the base class for you whenever the definition changes.

Try Jinn

Jinn’s alpha version is available for the Laravel framework and supports SQL databases.

However, it is built with other frameworks and databases in mind, so Symfony and MongoDB support is planned. Contributors are welcome to help implement support for these and other frameworks and databases.

Jinn’s full guide and installation instructions are available at jinncode.dev.

Looking forward to the feedback here or on GitHub.

--

--

Alex Shevchenko

Software developer and manager with 18 years of commercial experience.