# Hanami 2.0 App Structure

**URL:** <https://discourse.hanakai.org/t/hanami-2-0-app-structure/705>\
**Category:** proposals\
**Created:** [September 14, 2022, 3:14am UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705 "2022-09-14T03:14:48Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![dcr8898](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/dcr8898/32/625_2.png) [@dcr8898](https://discourse.hanakai.org/u/dcr8898)\
**Post date:** [September 14, 2022, 3:14am UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705/1 "2022-09-14T03:14:48Z")

</div>

## Summary

What app components should be in the `lib/[app_name]` directory? I propose that the `mailers` and `repositories` directories be relocated _outside_ of the “core business rules” directory.

## Discussion

First, I would like to express how excited I am at the recent progress on Hanami 2. I am stoked at the possibility of using Hanami on a new business project, and I don’t think I will be able to restrain myself from jumping in once 2.1beta1 drops. 🤪 Thank you all for your excellent work!

Please bear with me in the following discussion. I want to be complete, at the risk of being pedantic–and a lot of this stuff frankly is new to me.

### Hanami 1.x App Structure (for context and comparison)

In Hanami 1.x, multiple “apps” could be created in the `apps` directory, containing their constituent actions, views, and templates, etc. Meanwhile, the `lib` directory in the standard `Bookshelf` project, for example, would look like this:

```shell
$ tree lib
lib
├── bookshelf
│ ├── entities
│ ├── mailers
│ │ └── templates
│ └── repositories
└── bookshelf.rb
5 directories, 1 file

```

I recently built a couple of test projects in 1.3.5 to get my feet wet in anticipation of Hanami 2. In this process, it struck me as strange to have mailers and repositories inside the “core business logic” directory. Following the canonical “clean architecture” pattern, I would only expect to see interactors and entities in this directory (or whatever other organizational pattern you choose, thanks to Hanami’s flexibility!).

### Hanami 2.0 App Structure

In the Hanami 2.0beta1 announcement, a slightly modified app structure was introduced (although not fully fleshed out). For simplicity, the default “slice” is removed. Instead, the `app` directory will directly contain an `actions` directory (and presumably `views` and `templates`), until such time as the app requires further breakdown into slices.

```shell
$ tree app
├── app
│ ├── action.rb
│ └── actions

```

Now, in addition to the `bookshelf` directory (continuing this example), the `lib` directory will contain `tasks` for `rake` tasks. No mention is made of the proposed locations for mailers or repositories.

```shell
$ tree lib
├── lib
│ ├── bookshelf
│ │ └── types.rb
│ └── tasks

```

### Reasoning & Proposals

My interest in this question follows the logic of “clean architecture,” as described by Robert C. Martin. For me, this pattern is best summarized in the following diagram, taken from one of his talks.

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/hanamirb/original/1X/21c5e197deee3d348ef3d37ee51b9aa238650668.jpeg)

The goal of these boundaries is to isolate the business logic from from all of the ‘implementation’ details. In my mind, mailers and repositories should definitely fall outside of the business logic boundary.

So . . . what to do? I can think of two proposals, but neither seem ideal. The first, is to move `mailers` and `repositories` to the `app` folder, at the same level as `actions` (and, later, the various slices). Like so:

```shell
$ tree app
├── app
│ ├── action.rb
│ ├── actions
│ ├── mailers
│ └── repositories

```

The second proposal is to promote `mailers` and `repositories` _within_ the `lib` directory to the same level as `bookshelf` and `tasks`. Like so:

```shell
$ tree lib
├── lib
│ ├── bookshelf
│ │ └── types.rb
│ ├── mailers
│ └── repositories
│ └── tasks

```

I have to admit that neither of these proposals feels immediately natural or correct to me. I realize that `entity` objects are imported from the ROM-RB library, but I don’t think that should dictate the location of the directories. On the other hand, while mailers and repositories are “implementation” details, putting them in `app` feels a little weird, especially if the app evolves into slices.

## Ideas???

So, I would love to hear what others on the community think about this issue, especially since the app structure for Hanami 2.1 has not been established as of yet. What say you all? 🙂 I look forward to hearing your thoughts!

## Post Script

One of the reasons that I am interested in this question is the influence that DDD has had on my recent thinking. What would it look like to split a Hanami application into “bounded contexts”? I am thinking more along the lines of a “modular monolith,” such as Vaughn Vernon and others describe, than separately deployed microservices.

It seems likely that these bounded contexts might be sheared along different lines than the slices in Hanami 2. That is, I don’t think there will be a 1:1 conceptual correspondence between slices and bounded contexts, since they server fundamentally different purposes.

Where would repositories be placed in such an architecture? I’m skeptical of having them intermingled with the business rules directly, but they are coupled to some extent with their entity objects, and would conceivably be “bundled” into whatever container is created for the various bounded contexts.

For now I am going to focus on Uncle Bob’s clean architecture style (interactors and entities) and hope that Hanami offers me a pathway to a more modular approach by the time that I need it.

Thank you again for all of your wonderful work!

---

<div class="post-metadata">

**Author:** ![dcr8898](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/dcr8898/32/625_2.png) [@dcr8898](https://discourse.hanakai.org/u/dcr8898)\
**Post date:** [September 15, 2022, 3:43pm UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705/2 "2022-09-15T15:43:10Z")

</div>

The more I think about my last point regarding bounded contexts developing along different lines than slices, the more I understand the current configuration of having mailers and repositories in the `bookshelf` directory. If repositories and mailers are going to to be used primarily by the entities and interactors in their parent directory, then it makes sense to have them in the same directory as the interactors and entities.

Does this imply that there could be more than one directory in `lib` for different ‘bounded contexts’ (in DD terms) or ‘modules’ in Uncle Bob’s terms? That makes a lot of sense to me, but I haven’t seen any discussion of this in the documentation. How would namespacing be handled in such an arrangement in Hanami 2?

---

<div class="post-metadata">

**Author:** ![jodosha](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/jodosha/32/710_2.png) [@jodosha](https://discourse.hanakai.org/u/jodosha)\
**Post date:** [September 23, 2022, 10:55am UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705/3 "2022-09-23T10:55:09Z")

</div>

@dcr8898 Hey, thanks for your interest and the well structured proposal.

Not final decision yet, but I’m for Option 1: mailers and repositories in `app/`.

Reason: Hanami 1 had mailers in `lib/`, which made hard to access assets and helpers from `apps/`. If they stay in the same context.

---

<div class="post-metadata">

**Author:** ![dcr8898](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/dcr8898/32/625_2.png) [@dcr8898](https://discourse.hanakai.org/u/dcr8898)\
**Post date:** [September 28, 2022, 4:58pm UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705/4 "2022-09-28T16:58:48Z")

</div>

Hi, @jodosha. Thank you for your response. 🙂

I don’t have strong feelings about mailers, so I don’t know if their placement should follow the same reasoning as for repositories.

My reasoning for repositories basically follows the Clean Architecture diagram above. The repositories (Robert Martin called them “gateways”) are outside of the core business logic, but they are located on the bottom of the diagram, and not the left with the controllers and presenters, because they are “secondary actors.” According to him, they are invoked **by** the business logic. Based on this, it makes more sense to me now to keep repositories in the vicinity of the entities they serve. The same idea may or may not make sense for mailers.

One of the things I would like to see for Hanami 2 is the ability to have more than one namespace in the `lib` directory. Much like slices in the `app` directory, these could be used to group and organize complex business logic. If you practice DDD, these might correspond to the “bounded contexts” of the business domain. If you follow Robert Martin’s Clean Architecture, they might correspond to “modules” (he sometimes calls them “apps”). These `lib` namespaces **may or may not** correspond to the slice namespaces in `app`.

Brief aside: one of the things I really appreciate about the Hanami 2 alpha is the removal of slices from the default `app` structure. The same could be done with `lib` namespaces–add them only when needed.

Since the repositories are closely coupled to the entities used in Hanami 1.x (and presumably in Hanami 2), I think it makes sense to keep them in the same namespace. This would be even more advantageous if Hanami 2 also allowed `lib` namespaces to utilize different databases or namespaced db tables, possibly with different db users. This would help prevent database coupling between namespaces/bounded contexts/modules.

I see mailers as “secondary actors,” but they differ from repositories in that they do not derive from ROM and function much more like view objects and templates. However, I am curious how mailers would be invoked by interactors, for example (which I hope will be returning to Hanami 2 soon), if they were relocated to `app`.

Thanks again!

---

<div class="post-metadata">

**Author:** ![swilgosz](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/swilgosz/32/484_2.png) [@swilgosz](https://discourse.hanakai.org/u/swilgosz)\
**Post date:** [December 7, 2022, 7:37pm UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705/5 "2022-12-07T19:37:19Z")

</div>

I thought about using slices in different ways, and because of how slices can export some components, and because we can load different slices conditionally, I came up with this idea (don’t know yet how it’ll work out).

1. Use slices based on the interface type

```shell
$ tree slices
├── slices
│ ├── api
│ ├── admin
│ ├── web
│ └── client

```

1. Use slices based on the domain model

```shell
$ tree slices
├── slices
│ ├── ordering
│ ├── publishing
│ ├── booking
│ └── registering

```

I’m not sure, if allowing nested slices could help us group those different slice types together, but because I can do

```ruby
# config/slices/admin.rb

module Admin
  class Slice < Hanami::Slice
    import keys: ['interactors.order'], from: :ordering, as: :orders
  end
end

# config/slices/api.rb

module API
  class Slice < Hanami::Slice
    import keys: ['interactors.order'], from: :ordering, as: :orders
  end
end

```

I could merge those two ideas.

The `slice` for business domain does not need to even have the view/serializers folder, nor even actions in it. If you follow DDD terminology, you could look there for `interactors`, `commands`, `events`, `aggregators`, `repositories`, `mailers` etc.

For interface slices, you could expect to have some folders, like: `views`, `templates`, `contracts`, `serializers`.

If we would have a way to create nested slices:

```shell
$ tree slices
├── business
│ ├── ordering
│ ├── booking
├── web
│ ├── api
│ ├── admin
│ └── client

```

Then we could group them and have the file structure visually better.

At the moment, I’m just fiddling around with ideas, however, @dcr8898, I am a huge fan of event-sourced systems, CQRS and DDD and will happily attend all the discussions related to these architectural topics :). Thanks for starting this!

---

<div class="post-metadata">

**Author:** ![dcr8898](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/dcr8898/32/625_2.png) [@dcr8898](https://discourse.hanakai.org/u/dcr8898)\
**Post date:** [December 8, 2022, 2:35am UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705/6 "2022-12-08T02:35:15Z")

</div>

@swilgosz

Slices are probably already flexible enough to use the organization strategy you suggest. This approach is conceptually similar to the [Component-Based Rails Application](https://cbra.info/), which orchestrates groups of unbundled Rails engines, each of which can provide any of the usual objects available in a standard Rails app (controllers, views, models, helpers, etc.).

A Gusto team member recently gave a [talk](https://www.youtube.com/watch?v=J9S0qiGkAQY) at RailsConf describing how they use [Packwerk](https://github.com/Shopify/packwerk) to create “packs” (complete with defined, enforceable interfaces) in a Rails monolith. These packs sound very similar to the way you are suggesting to use slices in Hanami 2.

Much of what I proposed is based on ideas from DDD and Hexagonal/Clean/Onion architecture. The goal of all of these strategies is to isolate the business logic and protect it with clearly defined APIs. I feel that this can best be accomplished by sticking to the Hanami 1.x convention of placing business logic in `lib`, and by extending the architectural model by providing a pathway to modularization.

---

<div class="post-metadata">

**Author:** ![swilgosz](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/swilgosz/32/484_2.png) [@swilgosz](https://discourse.hanakai.org/u/swilgosz)\
**Post date:** [December 20, 2022, 1:41pm UTC](https://discourse.hanakai.org/t/hanami-2-0-app-structure/705/7 "2022-12-20T13:41:38Z")

</div>

@dcr8898 I’ve published a video, where I play with these ideas a little bit in terms of slices maintanance:

> **[Scale your app with slices!](https://hanamimastery.com/episodes/36-scale-your-app-with-slices)**
>
> In Hanami, you can reduce technical debt and keep fast development when the application grows. For that, slices is the key feature to revolutionize the way you think about web applications in Ruby.

I’m curious what will come out of these discussions in a year or two!
