 Okay, can I start? Do I need mine? Do I need mine? Okay, cool. Hi everyone and welcome to One Year With Hanami. My name is Gjegos, but for all these reasons people call me Greg. I work for a company called Kaleagal Solutions. We're based in Singapore and Manila. Now, I believe that most of you know what Hanami is, so the word comes from Japanese language and it is a long-standing tradition of welcoming spring, where Japanese people go together to park in the middle of the day, sit down, drink a beer, and just watch and enjoy the flowers blossoming. This name, this word was inspiration for for the name of the Ruby framework that was created, I believe four years ago by Luca Guidi, who's a Ruby developer. Initially he called his framework Lotus after some time he decided to change it to Hanami. So this Japanese word, because Mats is from Japan, Ruby is from Japan, this was the inspiration for the name of the framework. So a very brief introduction about the framework because I believe that even though I think most of the people in the Ruby community heard something about Hanami, they don't know really what it is. So Hanami is a so-called fully featured web framework as in that's how they call it on their own website. What it means is that it's not just related to web, but it also gives you the libraries, the codes to deal with other stuff like databases, like sending emails, like some additional utilities. So it's not only web as in take the request and respond, it's also additional stuff that is commonly used in web applications. Second thing is that Hanami is a modular framework. You can take any of the Hanami's libraries, any of the gems, there is around 10 of them, and you can just use it separately in your application without relying on the rest of the library. Third thing is that Hanami's lightweight. It's lightweight in terms of performance. At least that's what the website says. Like I didn't have, I don't have any experience with the performance issues with Hanami, so I cannot really verify it. However, it's lightweight in terms of the amount of code. So it is relatively short. It is most of the, most of the lines of files that you will see there are comments that that help document the libraries. And it's quite easy to read. Yeah, so the last thing is that Hanami promotes good practices, like it it puts testability of the code as priority. It puts modularity. It puts good engineering practice like dependency injection, etc. as the priority. I will talk more about it in a few minutes. Now, I have a production experience with Hanami. So one of the teams of Caligo started working on a new product and the long story short is that we chose Hanami because we wanted to choose something familiar. We didn't want to learn the new language. We didn't want to go for something that we could be afraid that at some point we will find a problem that we cannot solve. But also we didn't want to choose any obvious option like Sinatra or Rails. We wanted to choose something that we haven't tried yet. So the middle of this exploration and familiarity was Hanami for us. Now, we started working on our first Hanami application more than one and a half year ago. It was around January 2017. So one year with Hanami is actually a bit more, but we have one year of production experience with Hanami. So after six months of starting the first project, we launched it in production. We started working with the framework by then, so we started quickly working on the second application. And the last update for us was March this year. We updated our applications to Hanami 1.1. The current version of Hanami I believe is 1.3 or the current release candidate is 1.3. Jeff says that it's 1.2, so maybe that's the last one. I think 1.3 is in the better stage. So we haven't upgraded our applications to 1.2 yet. So any questions about how it's changed since 1.1, I cannot really tell you. Okay, so I will be talking about Hanami in four different parts. Because the framework itself consists of ten different libraries, I decided to split this talk so that I can tell you a bit about what we like about each part and what we don't like. So the first will be the web part, then the data part, then application, which will wrap the whole experience with Hanami. And the last will be support, which will include the utility gems and some ecosystem of Hanami. I will be talking about the things that we like and for this I will use green color on the screen and for the ones that we think could be improved, I will be using red color. Now, so let's start with the web. This part will consist of four gems. So the first gem is a router. Router basically takes HTTP request and it directs it to certain controller. There is nothing really special about it, so I will skip this gem. You just need to know that it does what it should do. It's kind of like a Rails router. You put your routes in a separate file. It's not Hanami style where you put the path in the name of the method. It's a separate file. The second gem is controller, which takes the HTTP request and it responds with the rack format. So it gives you an array with the HTTP code, the body and the headers. The third is the view, which is an object that encapsulates the logic that will go back to the user. And the last one is helper that helps with formatting code with stuff like currencies, numbers, strings, etc. So now the first thing that we really like in Hanami is the fact that one controller action is one class. So unlike Rails, you do not put common actions together in one file in one controller. Just one action is one class. That makes it really easy to test that the code is a bit cut. But basically how you call an action in Hanami is that you create a new object of the action. So you do action.new and then you call the method called call with the parameters that you want to pass there. So if you work with Rails, then you know that to test controllers, you need to make kind of a fake HTTP request. You cannot just initialize controller. If you call, I don't know, users controller.new, it will throw an error that you cannot initialize it. So in Hanami, the actions, the controller actions are just normal objects that you can create. You run one function of them. You just define one function and it gives you a result. So the basic structure of your application will look something like this. You have the directory called apps, then you have the name of your app, then you've got controllers and each resource is a directory here. So if I want to have two actions, index and create for orders, I will have the directory called orders and then action called index, which is one file action called create, which is another file. Now the problem with the actions and the controllers in Hanami is that they are a bit magical. The only thing that you need to do in Hanami to create controller is just create a file and put the function called call that takes the parameters that are passed from the client. So now the problem is that you see my method here returns a string that says this is action. But if I call my method, if I call index.new.call, then it doesn't return the string this is action. So now the question is what happens there? I have a function called call. I call this function and it doesn't return the string that I return. So this is the magic that Hanami provides. Basically what happens is that it wraps your response in this array of free elements, which is HTTP code, then headers and then body. So if you want to customize the body or status, you have to use a method. Status then you provide HTTP code and the body or you have to modify the accessors. You have to modify the body and the status of your HTTP response. Why I don't like it? This is because I need to rely on a mutable state here. So the action itself to return something I need to modify the body of this action. And Hanami as the framework that promotes good engineering practices also promotes immutability of the objects. But the actions, the controller actions are kind of incontrary to do that. So I believe that it would be easier if we just return some result object from this call method. And that would be this array in the end. So yeah, that was the second thing. Now the third thing about the web part is that views are not templates. This may be confusing at first if you have been working only with Ruby on Rails as a Ruby framework. So in Rails, you put lots of logic in your templates. And the place when you want to extract that logic from a template, the place to do it is a helper. Now the problem with helpers is that they are included in all the views that you have. So for example, if I define a method called I know name in the user's helper, I can call it in others helper, sorry, in others view. I can call it in any view. So basically helpers in Rails are like this one big huge dump that everything that goes to any of them, it ends up being included in all the views. This makes it very difficult to maintain separation between your views. So in Hanami, the view is actually an object that contains the logic. And this object is available for the template. The template is a JSON or HTML or whatever you want. And the ideal template in Hanami shouldn't contain any logic. It shouldn't have any, I don't know, any formatting, any SQL queries, any calling to the models. It should just call the functions that you make available in the view. So this is an example. I've got a class called index. It's called the same as my controller class except that it's a view. So I include the view module there. I define a method called user's age and then I only call this method in my template. So this is kind of an ideal template in Hanami philosophy. It shouldn't contain logic. It should just call the functions that are available to it in the view. And I cannot call the user's age in a template that belongs to orders or some other resource. This method is only available in this particular template. If I want to have some shared methods, then I need to extract them to a separate module and I need to include them in different view objects. So this is something that we really enjoy in Hanami because it forces us to have a good separation between the logic and the presentation. Another good thing about the web part is that built-in helpers are private. So Hanami has this gem called helpers that gives you stuff like format number, for example. And these helpers are not public methods. You cannot call format number in the template directly. You have to add a public method in your view and then only there you can use this helper. So I'm not entirely sure if all the helpers are private, but the guidelines say that you shouldn't use these helpers directly in your object. So here's an example. You see, I've got the format number that comes from the helpers gem and I do not put format number in my template. I just put total cost and this method uses the private helper that is format number. So again, we do not put logic into the template. We just call the methods that are in the view. Now this makes it, in combination with the previous part, makes it very easy to test your views because to test your view you do not open the page and you do not use any HTML scraper to check whether your content is there. You test the view as a normal Ruby object and because you do not put any logic in the template, the template doesn't have to be tested because it is just displaying the methods that you can already test. Okay, time for the second part, the data. I think that's normally the most interesting part because it includes the model which is always somehow controversial and it causes some heated discussions. So Hanami has a gem code model that helps you interacting with the database, the collections and in general data flow. It has the gem code validations that is separate from the database validations. I will talk about it in a moment. And it has an experimental gem code event that is supposed to help you with producing and consuming events. It is experimental because it doesn't have an official release yet. I only saw the repository and checked more or less how it works, but I don't have any real experience with this gem. So I will not be talking about it. I just wanted to mention it as something that will be probably an official part of Hanami framework at some point. Okay, so the first great thing about the data part is that Hanami uses a repository pattern as in opposition to some other patterns that you can have in the database like DataMapper or ActiveRecord. Repository pattern forces you to separate collection of objects from the object itself. So you will not have one class called order, which will have scopes so that you can query the database and with instance methods that you can call in a single object. No, these things are entirely separate. So repository itself is not necessarily tied to a database. Repository is a collection of objects. It can be an array, it can be a flat file. The storage doesn't matter. It just means that you have collection of entities, but the entity itself is a separate class. So for example, I've got order repository that defines some associations and that defines the scopes. So for example, I can call order repository a new dot future and it will take the orders that will be delivered in the future. Now the order itself is a separate class. It's an entity. It is mapped to order repository because of the class names. So if I say order repository, it will know that when I want to fetch some orders, it will use the class called order to create these entities. But they are separate concepts in Hanami. Also an interesting thing is that the where method is private. You cannot call orders dot where outside of this class. So it doesn't give you access to the database. Like from outside of this repository, you cannot interact with the database. If you want to define certain interaction like fetching the future orders or past orders, etc., you have to add new public method. This makes it very clear in what ways other classes are able to interact with the database. Without it, if the method dot where or some similar methods are public, then you don't know who queries the database in what way because everyone can do it in any way they want. So here you just give a very clear interface of what queries are available outside of this class. The not so good part about Hanami model is that it relies on another library that is called ROMRB that relies on another library called SQL that is interacting with the database. So why is it not good is that each of these libraries have different abstraction. So SQL library is the lowest level of abstraction. You can use SQL library to almost generate a raw SQL. Now ROMRB is higher level. It doesn't generate the SQL directly but because of that it has a bit limited capabilities. And the same with the Hanami model which is on top of the ROMRB. Its capabilities are even more limited. Now this thing changed from version 1.0 to 1.1 but we still have situations where we cannot use Hanami model to fetch the data that we want from the database. So we need to go one layer down and then it appears that ROMRB also might not support what we need. So there we go, one layer down. And this causes a lot of confusion because you never know which layer of abstraction you should be using at the moment. And that makes it also difficult for developers because if you want to make some complex query you might be reading documentation of three different libraries to find the solution for your problem. Now validations. Validations in Hanami are a separate gem and are a separate concept from storage or from controller or basically they are a mixing that you can include anywhere in your application and you can validate the parameters that you are passing to the class that includes these validations mixing. So you can use the same gem to validate to perform the database validations, to validate the data that will go to the database and you can use the same gem to validate the patterns that are coming from the user from HTTP request. Okay, so an example is I've got one controller that is called create and I define params, this is just a sugar syntax for the Hanami validations and I said that I require title to be a string and I require amount to be an integer. And then I can include Hanami validations in my other class which is a service object and I just say validations do and I use the same DSL for defining my validations. This is awesome because you can define your validations in any place of the application whether it's a service object or controller or the entity anywhere. Basically validations are not tied to the database they are just tied to, I don't know, I think that you need to pass a hash there to be validated and that's it. Okay, now time for part three which is the whole application and here we'll be talking about two gems. The first gem is called Hanami and it's an application gem so this is the whole framework that consists of all these gems that I mentioned before and a few more and it also adds the concept of application. So if you want to use any of other Hanami gems you can use them separately but this gem, except for including all the other ones it also gives you the concept of application and it provides a lot of configuration for you it helps you build the application in an easier way. And the second gem, this is something that I won't be talking about, it's CLI it just gives you generators for migrations, models applications, stuff like that. It's not very interesting, it just that's what you expect it to do it just helps you generate the code in an easy way. Okay, so first great thing about the Hanami gem itself is that the mountable applications are first class citizens. If you work with Rails you know the concept of Rails engines that were added around, I know, like seven years after Rails where the framework was created. So by default in Rails you've got one application then if it's too complex, if you want to separate different concepts then you can add mountable applications that are called engines. In Hanami the mountable applications were built into the framework almost since the beginning. So using multiple applications in Hanami is not a special case, it's just by default you have multiple applications. The fact that you might have only one application because you don't need more, this is a special case. So what it provides is that the multiple applications are not special in any way. There is no difference whether you work with one or multiple applications, the whole framework is built on the concept of supporting multiple applications. So you will not be fighting against the limitations that Rails engines might have. So yeah, the structure of the application by default you have that directory called apps and by default you have an inside directory called web but you can add any other applications that you want. Each application has a separate controller, separate views. I think they have separate configuration and if you want to have some shared code you just put it in lib directory instead of apps directory. So for example at KaliGo all our repositories or our entities and some shared libraries are just put in lib and config controllers, views, etc. are put into separate apps. I think assets also can go to like style sheets, JavaScript, etc. also go to separate applications. The thing that I don't like that much about Hanami is that the gem Hanami is not very modular. So the Hanami ecosystem, it is. All these gems I can use them separately but if I want to build Hanami application and use Hanami gem it will come with all the other gems I think except for the model. So even if I don't need mailers it will be in my gem file log. Even if I don't need assets, even if I don't need views because I just want, I know, I want to use only controller it will still be, these gems will still be there. So this is not bad per se because most of the frameworks have it this way. I consider the problem because Hanami promises the modularity and this modularity is limited. So if I want to use the controller gem itself I can but if I want to use controller and view and that's it then I have to write the whole application from scratch and if I decide to instead use the Hanami application then it comes with all the seven or more gems included. On the other hand a very good thing in the framework is that it promotes good practices. So I already mentioned separation of layers like validations are separate from the storage. Views are separate from the templates and separate from the helpers. Hanami promotes practices like making as much code as you can private so that you define very clear interfaces of how the classes can interact with each other. Making code easy to test is one of the priorities for the Hanami core team. So the classes are very easy, controller actions, view objects are very easy to instantiate and to test. So this is something that it's extremely good feeling to know that the framework that you are using promotes the good practices. Well your code of course still can be a spaghetti code but Hanami makes it easy to write good code. It makes it more difficult to make a mess. So you still can do that but you do not need to fight the framework to use the good practices. It helps you with that. Okay now time for the last part which is support and here we've got two gems. A gem called Mailer does exactly what you expected to do. It sends emails. It has some simple DSL to define the recipients, to define the S&TP settings, et cetera, but nothing more than that. And the gem called Utils that's more interesting and there are a few reasons why it's so interesting. First is that this gem doesn't manky patch Ruby. So all the classes like if Hanami core team wants to add a method to string, they have their own module called string. Initially it was a class that wrapped the string that you had. Right now it's a module so you do not call the method on the object, you just call the method on the module and pass your string as the first argument. This is great because if libraries that you use commonly manky patch Ruby then you start getting lost. Like which method is the Ruby method which is the method of the framework? Manky patching of the framework might cause a lot of issues. Imagine that one of your gem that you're using in your application relies on some other gem that relies on some other gem that relies on active support that manky patches like 20 different classes. This is something that if you work with Rails you just get used to active support. But if some other gem deep in your dependencies depends on manky patching then this is very confusing because this is not your code that manky patches Ruby. It's something that you accidentally have on your list of dependencies. So I really appreciate that there is no manky patching in the Hanami framework. One of the great things that Utils gem provides is interactors. These are basically service objects that help you to have standard way of defining the domain layer, the services layer. So this gem is not really great. I'm not a huge fan, but I like the fact that there is a standard way in Hanami to deal with the service layers. Very few frameworks do that. So what I'm not a huge fan of it is that interactors are similar to actions as in to return a value you need to modify the state of your current object. Here's an example. I've got a class that's called create user. I have a method called call and to return some user from that I need to modify the instance variable code user and I need to expose it via expose method. So this is not that bad because this state, this at user, this variable is not available from the outside on this create user class. So you only modify private state. So it's not that bad. But still, for a framework that promotes so many good practices, I believe that it could be done via retailing explicitly some result object. And the last thing, this is not a problem in the framework itself, but this is a problem that you will find when you start working with Hanami. The ecosystem is small. If you want to have authentication added to Hanami, there are a few options. Probably none of them is generic enough for you, so you will write your own library that you will release as an open source, but it will not be generic enough because it will be just for you. So then people will have four options and still they will be writing their own solutions. So there is just no very good authentication library. We were working with Webpack, I believe sometime ago, and the only library that helped to deal with Webpack in Hanami was limited to one application per repository. And as I said before, Hanami is built around the concept of multiple applications. So having multiple applications wanted to use Webpack, we had to write our own solution. So again, the Hanami coding does a really great job with the framework, but only so much depends on them. So the ecosystem is still small, the popularity of Hanami is growing, but if you want to build applications that rely on lots of external APIs and you don't want to write your own integrations, you will find it very slow for you to develop the application. Okay, so to sum up, as can we go, we are very happy with the Hanami framework. We've got two applications running in production. Some of them are pure APIs, some of them are using views. We had to write quite a bit of our own code, some boilerplate code, but overall we are very happy. So I believe that you can use Hanami for most of the web applications that we are planning to develop and even some non-web applications. You will not use the controller gem if you're not writing web application, but you can use the model gem or the mailers gem or some other libraries. On the other hand, if you want to build applications that rely heavily on external libraries, probably you should reconsider. If you're writing a project with lots of complex database queries, you should probably reconsider because you will find yourself juggling between three different layers of database abstractions. And if you write simple crowd applications, probably you could use something that will help you generate almost all the code because, well, it's just going to be simple crowd application, right? Yeah, so that's it. As I mentioned in the beginning, I work for a company called Collegial Solutions. We are using Hanami, Rails, Elixir and some other stuff, and we are hiring developers in Singapore and Manila. People call me Greg, but my real name is Gregosh, and you've just listened to one wonderful year with Hanami. Thank you. Questions time. We have some rewards for people who have questions. What is that? It's a mousepad from JetBrains. Nobody can ask myself a question? No? Jeff, go ahead. What's been your biggest challenge integrating interactors, which I understand has mixed experience with into the rest of Hanami application, specifically in terms of things like error reporting and validation. Because the conceptual models for error checking are so different, say you've got a controller action that calls an interactor to do its business logic, and the interactor deals with a confluence of inputs to produce the result. And so errors that are reported might not depend on any single afternoon. But if you're in Hanami validations on the premise block and your controller action, and say your amount attribute is not an integer, that seems enough to roll with. But if you have, let's say you pass off to this interactor, and the interactor says, no, this amount is not allowed because of this other condition. Okay, your interactor has a string error message that gets sent back to the controller action. Now the controller action has to use the input form and or flash messages to communicate that error to the user. That's been one of our continuing headaches, is what's the best way to end that? I don't know what's the best way really. So the framework said that the Hanami interactors don't help you with that. It's just like, it's a small library that just defines how you interact with the services. Yes, yeah, so I don't think that there is a difference whether you're using Hanami interactors or whether you use some dry transaction or whether you use some other library. So what we normally do is that our interactors define whatever result object you want, whether it's a user or other or whatever, and the errors. And then we just ensure that it can only return the errors that controller can pass further. So basically the Hanami interactor may internally log in some details about the error, but the actual error message that it gives back is something that can easily go to the user. So the controller doesn't have to map any error codes from the interactor to the user. Yes, but again, this is not the best solution. This is just something that from all the things that we've tried causes us the least number of problems. Yeah, exactly. Still painful though. Okay, any more questions? Yeah? What kind of application are you guys thinking of? Well, I think that it's really good for any kind of web application. Unless you have one of these cases that I mentioned, I cannot tell you that it's good for business applications or stuff like that because you can develop good code in any other framework. You can develop equally good application in Ruby on Rails. So I don't think that there is any specific use case here. We are using it for one of the cases that we have is a pure API application that is used by multiple clients all over the world. And the fact that we have separate classes for each action and that we have kind of built in interactors layer helps us because from the beginning we knew that we would be having very heavy services layer. So having a very well-defined structure of this layer helped us from the beginning. So if you know that you will be doing more stuff than just create, update, delete, then probably it's good to use something that already has or if you want to use another framework like Sinafra Rails, then you should immediately find a good third-party library that will help you with this layer. But yeah, in Hanami you just don't need to look for it. It's already there so you can immediately start building a heavy services layer. Yeah, thank you for the question. I'm going to comment on the last question. We're building an app with Hanami. They use it as a web app and an API. We have an API that we are bringing up a phone app, an iOS app that is using our API. And we're using COI stuff and DevOps. And they all use the same models. They all use the same interactors. They all use the same authentication. They all use the same authorization. Okay, it's all Hanami. That's why we love it. That's why we 90% love it and 10% hate it with a purple flame passion for rough edges like what we were discussing earlier about the mismatch in error paradigms. But it is still a very young framework. Rails has been around for about 15 years now, 12 years. So if you're going to have to use a lot of APIs... That also gives me an idea. Imagine that you have an application where you have API and API has some token authentication and then you have the web part where you have password and session authentication. And if you use Rails, then in this case you will have to define the authentication per controller. So you need to know that controllers either in this module or just for each controller you need to define which way of authenticating it uses. In Hanami you just put it into separate applications and they have separate configuration. So if you put stuff into the API application it will always use this API authentication. You cannot mix it up because they are kind of like separate projects that are just using some common shared libraries. The other thing that is simple is intended to be your app that is independent of the delivery mechanism whether it is a web app, an API, a CLI or some other app. Like you may have read about six or seven years ago there were these bunch of articles talking about how you should vendor everything, make your whole app a bunch of gems. The whole point of the Live Directory in Hanami is you can turn around and turn that into any kind of new app. Yeah, that's a good point. Yeah? Sorry, sorry. Sorry for any further discussions offline because everything is in the fix right? Sorry, thank you very much. No worries, thanks. I'm going to turn it off. Yes.