In a previous post I did a bit of a comparison that was looking at the differences between Rails and Java’s Spring framework when it came to bootstrapping a new application in order to provide a “batteries included” kind of experience.
I made a note there that I hadn’t really looked at other comparable solutions in other frameworks but that I thought it might be worth exploring to see what efforts might make sense to bring to Rails land.
Starting Premise of My Post
- Many developers (myself included) are lacking guidance about how to grow “real world apps” with just a purely MVC approach. That is to say basically nothing of the split for many between front and back ends (i.e. SPAs etc)
- There are large subsets of functionality that are extremely common in most applications for which we don’t as yet have a “Rails way” of approaching so much as we have “a handful of popular gems”.
- We have collected 10+ years in many cases of data from real world solutions as to how well those existing solutions and patterns work and as such we might want to think about any “grand unifying theories” to these problems that keep popping up (i.e.
eventsas a small number of examples).
- It is the role of a framework like Rails to provide developers with what I would probably describe as really well crafted building blocks which can be put together in order to build an application while still acknowledging that in some cases people have very specific needs and allowing them to bring their own solutions if needed.
- By comparing and contrasting Rails internal frameworks and primitives against those of other comparable ones we can not only begin to identify where some of those gaps might be and discuss the relative pros and cons of their approaches.
The joy of Rails is ultimately underpinned by 3 main things:
- Ruby is a really expressive language and is generally a pleasure to code in.
- Rails provides a good “out of box” experience precisely because it has a set of really well crafted primitives that abstract away a number of hard parts of web development.
- The combination of these two things are what makes it such a good choice if you want to deliver real world applications in a short amount of time.
I’m making the argument that this is possibly under threat precisely because we are missing “the Rails way” to a whole bunch of problems and everyone is kind of doing their own thing at the moment and it I get the feeling that it is a bit of a mess once an application reaches a certain size.
I saw a tweet last night from Adam Wathan (creator of Tailwind CSS) that said:
The only problem with Laravel is that you have to subject yourself to writing PHP to use it It’s better enough to be worth it though in my opinion.
I think that is a claim worth at least exploring and discussing both as a community and maybe to get some further thoughts from Rails core team in particular.
Let’s start by looking at Laravel’s
/app folder structure
/app folder inside a Laravel project is very similar to a Rails one in the sense that it is designed to handle all of the core code for your application and almost all of your classes for an application would live here.
Note: I’ll start by saying that I am almost certainly going to do a crappy job of covering this properly and you should take a look at the official docs for this here.
However, you have the following sub-directories to help you organize your code:
Broadcasting: This folder is for code relating to the concept of broadcasting events via WebSockets and I guess would be roughly equivalent to the
channelsfolder in Rails.
Console: Code for running various
commandsand scheduled jobs in a way that looks similar to Rake tasks
Events: Events are a good example of a pattern which is extremely common in modern web applications across comparable frameworks but is missing from Rails. To be fair that isn’t technically true because while we do have gems like
whisperfor example and we also have this recent change which took
ActiveSupport::Notificationsand made them suitable for a general event system. However, I would make the argument that many people seem to be unaware of it as it was historically used for a different purpose and that we might still be missing some Rails magic on top yet.
Exceptions: A folder for creating custom exceptions and any code associated with how exceptions are logged, rendered and generally handled.
Http: This is as far as I can tell more or less the same as
app/controllersin Rails land.
Listeners: This is basically the other half to the concept of events.
Eventsin turn have
Listenerswhich will run in response to any Events that piece of code is registered to Listen for.
Notifications: This is an interesting abstraction from Laravel. Think of
Notificationsas any kind of transactional notifications that are sent by your application. Laravel’s notification features abstracts sending notifications over a variety of drivers such as email, Slack, SMS, or stored in a database.
Policies: This folder contains all of the authorization policy classes for your application. Right now this is another good example of something where we have a number of competing solutions to this in the Rails world right now but no “official way” despite the fact that most applications need this. For the record I think a project like
Action Policymight be a good starting point for that conversation.
Providers: Laravel has the concept of
Service Providerswhich is described in the docs as: Service providers bootstrap your application by binding services in the service container, registering events, or performing any other tasks to prepare your application for incoming requests..
Rules: Rules are used to encapsulate complicated validation logic in a simple object.
So already I can start to see some interesting patterns and abstractions emerge. Of particular note to me is:
- Events & Listeners
- Complex validation through Rules
Other Interesting Concepts / Primitives & Frameworks
At the risk of making this post impenetrably long I am just going to leave this section as a extremely brief whirlwind that is just designed to serve as a starting point for conversation and potential inspiration.
Service providers are the central place of all Laravel application bootstrapping. Your own application, as well as all of Laravel’s core services are bootstrapped via service providers.
But, what do we mean by “bootstrapped”? In general, we mean registering things, including registering service container bindings, event listeners, middleware, and even routes. Service providers are the central place to configure your application.
The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection. Dependency injection is a fancy phrase that essentially means this: class dependencies are “injected” into the class via the constructor or, in some cases, “setter” methods.
Facades provide a “static” interface to classes that are available in the application’s service container. Laravel ships with many facades which provide access to almost all of Laravel’s features. Laravel facades serve as “static proxies” to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.
Laravel’s Contracts are a set of interfaces that define the core services provided by the framework. For example, a
Illuminate\Contracts\Queue\Queuecontract defines the methods needed for queueing jobs, while the
Illuminate\Contracts\Mail\Mailercontract defines the methods needed for sending e-mail.
Each contract has a corresponding implementation provided by the framework. For example, Laravel provides a queue implementation with a variety of drivers, and a mailer implementation that is powered by SwiftMailer.
Potential Points for Discussion
- Is there anything from the list above that inspires a strong feeling either way that you would or wouldn’t like to see?
- For those of us with some level of experience in other frameworks what are the things you miss most when having to work in Rails?
- As I mentioned in my previous post, I don’t work professionally as a developer at all and as such I feel like there is a strong potential for a big disconnect between the points I raised in the premise section above and the wider community. I’d love to hear peoples thoughts on that.
Finally, I haven’t covered this at all in this post because I got the impression that some things are very clearly in the “out of scope” category but Laravel has a whole bunch of really polished looking solutions for things like Deployment, Multitenancy, Customer Billing, Authentication and Administration.
However, I am extremely curious to hear what people think about this and where they see Rails continuing to fit into the potential list of choices for the kinds of people who have traditionally made up the core audience of Rails (i.e. People who have an idea that they want to turn into a code and potentially a business in a quick and sane manner).
I have an entire argument that goes roughly along the lines of:
- Rails has traditionally not had much in the way of strong competition for people with those kinds of goals as as such it has been easy to ignore. However, that is no longer true and it’s not even obvious that Rails is even the best choice right now for developers in a situation like that.
- There is a huge amount of potential real world impact (primarily through upwards social mobility and the general ability to deliver solid technical solutions to common problems) that could be realised if we made those kinds of tools available to the Rails community.
- Every time an otherwise good project never ships because people ended up getting caught up in these kinds of topics it is a tragedy and we should be thinking about how we as a community can ensure that happens less often.
I would obviously love to hear peoples thoughts about that also and if you made it this far please accept my very sincere thanks for your time, I know this was a bit of a monster post