How I Structure my Humming-Bird Projects
Tags: raku, webdev
Published: 2023-03-19 23:45:30

[Humming-Bird](https://github.com/rawleyfowler/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:

```raku
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](https://github.com/softmoth/raku-Template-Mustache), but you can also user other templating languages like `Template6` by the [Raku Community](https://github.com/raku-community-modules/Template6), or `RyML` by the dashing [tony-o](https://github.com/tony-o/ryml).

**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](https://github.com/FCO/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](https://github.com/FCO/Red) gives you. Because of this, I typically use [DBIish](https://github.com/raku-community-modules/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](https://github.com/rawleyfowler/Humming-Bird/tree/main/examples) to see some existing apps, and check back soon to see the full-fledged `MVC` example. 

Thanks for reading, Raku rocks!