1. 7

  2. 4

    I hear about Hanami for the first time. I’ve browsing the website for a bit to figure out what it is about, but I’m having a really hard time. A lot of the content/text on both the website and the introduction basically says nothing.

    It’s evidently a web framework.

    There is claims like “Full-featured, but lightweight”, where it claims that it uses less memory than other frameworks, no information, which, why, how and under what circumstances.

    There’s also a claim “Simple and productive” describing how you can just start writing code and in Getting Started it starts with “this learning process can be hard” in bold.

    The “Download, Develop, Deploy in 5 minutes.” in “Develop” just tells me how to add a dependency and how to commit all contents of a Directory.

    Overall, given that Ruby has no shortage of web frameworks I didn’t find any information that sets it apart.

    1. 7

      Hanami 2.0 is significant because it is basically a complete rewrite that uses dry-rb as the foundations of the framework.

      At a very high level, think of this as a web framework heavily inspired by FP rather than Smalltalk or Java. It emphasizes immutable data structures and function composition.

      The most important, fundamental abstraction is dry-types. Instead of ad-hoc, procedural type checking, you instead write type objects with an expressive DSL that produces composable functions. These functions are understood by the rest of the system as constraints.

      Building on types, dry-validation is an expressive DSL for validating complex Hash structures like JSON data. Schemas contain keys and type values, and can be composed together. Validations encapsulate schemas with more complex rule logic. Keys and values are coerced into a standardized format as a byproduct of validation.

      Validated data is represented as immutable struct objects. Structs don’t get instantiated until they are validated, so you never represent struct data in an invalid form.

      Hanami uses ROM as the persistence layer, which follows all of these principles as well: your database structure is not tightly coupled to your domain objects and there are abstractions in place to make moving between them easy. Your domain objects are immutable, dumb values and your persistence logic lives in an entirely difference place. You can write Repository objects to be as simple or complex as you need. Querying is a Relation object separate from everything else but easily accessible within Repository.

      Business logic is expressed as functional Operation objects that share a result type via dry-monads. Operations have a very convenient “do notation” syntax that unwraps monads with yield, flattening out results from other functions into a top-to-bottom execution that halts on failure without dealing with the downsides of exceptions. Monads are very convenient wrappers to pattern-match against.

      All dependencies in the system are addressable via dry-container as a string key, and are injected as arguments using dry-auto_inject. This means that your Operation classes act like IoC containers, and the instances they produce act as functions. The container system understands how to construct your function objects, so you never have to do it manually.

      Your containers can be split up according to business domain as Slices. These slices are testable in isolation from one another, providing a clean separation of concerns without dealing with the overhead of e.g. Rails Engines.

      The project structure itself it provided by dry-system, so you have complete control over every aspect of how your code gets loaded and where it lives. Maybe one slice is more convenient to develop with code reloading, but another slice can just be required once. That is under your control.

      Environment settings are strictly type-checked with the same dry-types objects you use everywhere else.

      Providers are kind of like Rails initializers, except they can be loaded from gems and they describe a dependency graph between them. This allows you to cleanly instantiate your system dependencies without doing dumb stuff like prefixing initializer files with numbers to get them to load in a particular order.

      1. 3

        Thank you! :)

        Would be great to make that information available on the website. I know it’s a bit out of fashion to having meaningful, informative websites rather than generic headings, seemingly random claims, fancy words and “who is using” lists, but I think that I might not be the only one, who’d prefer actual information upfront.

        In best case, like good man pages there should even be short-comings or at least non-goals.

        Sadly it seems that these things don’t sell.

        Anyways, thanks again for writing a summary.

        1. 2

          I wouldn’t say Hanami lacks inspiration from java or smalltalk. e.g. the IoC bits are very similar. In general I’d say that Hanami relies on different paradigms for each layer rather than pretending one paradigm can properly address every problem. Disclaimer: I’ve only built one small project w/ Hanami.