Humming-Bird is a very unopinionated web framework. It allows the developer to structure their projects however they like. As the creator of Humming-Bird I can openly say that this was on purpose, and takes after a few other popular frameworks.
Though this was on purpose, it can seem daunting, especially to people new to the Raku ecosystem, or new to designing web-applications in general. I hope to underline the few structures I have employed to making sure my application makes sense from a developers point of view, but also from a Raku point of view.
The Single File Service
If you find that your service will be small, you may want to consider building your system in a single-file. This is done very simply with a structure like:
App-MyService/
├── bin/
│ └── my-service
├── lib/
│ └── App/
│ └── MyService.rakumod
├── META6.json
└── Dockerfile
In your META6.json
you'll have:
...
"provides": {
"App::MyService": "lib/App/MyService.rakumod"
}
...
Then in your bin
file you'll want to import your service, and Humming-Bird, something like:
use Humming-Bird::Core;
use App::MyService;
listen(1234);
It is important that you import App::MyService
after Humming-Bird::Core
to avoid having some weird side-effects with route declarations in your service.
Model-View-Controller
Some web-apps would prefer to be elevated above the status of service, and would prefer to have a dynamic UI. This is typically done with the Model-View-Controller
or MVC
architecture. In a typical MVC application you separate concerns between the model, the view, and the controller by keeping them in separate name-spaces or folders.
With Humming-Bird, nothing really changes except that your views
probably don't have to be individual Raku modules. I like to structure such applications like:
my-service/
├── templates/
│ ├── foo.mustache
│ └── bar.mustache
├── bin/
│ └── my-service
├── lib/
│ └── App/
│ ├── MyService/
│ │ ├── Controller/
│ │ │ ├── Foo.rakumod
│ │ │ └── Bar.rakumod
│ │ └── Model/
│ │ ├── User.rakumod
│ │ ├── Friend.rakumod
│ │ └── Post.rakumod
│ └── MyService.rakumod
├── META6.json
└── Dockerfile
You'll still want the same use
statements in your bin
file, but this time you'll have to do a provide in your META6
file for each of the nested modules.
...
"provides": {
"App::MyService": "lib/App/MyService.rakumod",
"App::MyService::Controller::Foo": "lib/App/MyService/Controller/Foo.rakumod"
...
},
...
Now you can layer your code nicely, having the controllers call to the models to get data, and then rendering pages based on your templates. In this example I used Template::Mustache
by softmoth, but you can also user other templating languages like Template6
by the Raku Community, or RyML
by the dashing tony-o.
Note: this is following an "Active-Record" approach to database management, where the sub-class of a type handles Repository
type actions. You can use either. If you are looking for an "Active-Record" style database manager ORM thing, you can use Red.
Microservice
With a microservice I'm typically more focused around data and its flow, because of this, I adapt my single-file structure to also have a Repository
section, allowing me to nicely package my database interactions. I also like to have a Queue
or Communication
module that handles talking with other service if I need to. This typically includes talking to queues, or establishing other UDP
or TCP
connections.
With Microservices I prefer the more fine-grained Repository
approach where I can hone in on writing fast SQL vs the "Active-Record" approach that something like Red gives you. Because of this, I typically use DBIish for microservices.
My simple microservice structure typically looks like:
my-service/
├── bin/
│ └── my-service
├── lib/
│ └── App/
│ ├── MyService/
│ │ ├── Communication/
│ │ │ ├── Queue.rakumod
│ │ │ └── Upstream.rakumod
│ │ ├── Repostiory/
│ │ │ ├── Foo.rakumod
│ │ │ └── Bar.rakumod
│ │ └── Controller/
│ │ ├── Foo.rakumod
│ │ └── Bar.rakumod
│ └── MyService.rakumod
├── META6.json
└── Dockerfile
This blog post was fairly erratic, but I hope it demystified a little bit about project structure using Humming-Bird. I'm currently writing a small MVC
example for Humming-Bird, make sure to check the examples directory to see some existing apps, and check back soon to see the full-fledged MVC
example.
Thanks for reading, Raku rocks!
Top comments (4)
Hello, thanks for Humming-Bird and these blogs explaining how it works. Would you mind writing up something on creating simple tests for a Humming-Bird app or are there already examples out there?
Hey thanks! Sorry I haven't been on dev.to for a while. In the future if you need to contact me, please send me an email!
One of the next features I would like to write is a integrated testing tool for Humming-Bird, but for the mean time if you look in the
t/
folder of the project you'll see how easy testing applications is. Typically you'll pull theroutes
from the app and pass requests by hand.No worries, I did try to lurk you on Fedi/Mastodon but it looks like we haven't converted you to our commune yet! I'll shoot you an email next time. 📬
I'm excited about the testing tool. I'll take a look at your current tests in the meantime as I need to learn the 'Raku way' of doing things in general so it'll be a useful exercise for me.
Actually I'm on here to make a new post, so make sure to check that out too :D