原文地址:http://theaudaciouscodeexperiment.com/blog/2014/03/17/hexagonal-architecture-guidelines-for-rails/。

TL;DR

Good application design is hard and there’s no one “right” way to do it.

I often get asked the how I design decoupled applications and while there’s no easy answer I’m going to lay down the rules that have worked for me.

Background

Rails gives you a very minimal architecture of three parts (MVC) all three of which have proved inadequate to contain any real amount of complexity. Remember fat models, skinny controllers?

This is in stark contrast to ‘enterprise’ frameworks which is often criticised for providing too much complexity up front.

The key is to start with just a couple of extra layers and keep those layers decoupled so that more can be added, allowing you application to scale in complexity with ease.

The Rules

  • Controllers actions are allowed a single line of code
  • The application doesn’t return anything to controllers
  • The application has no knowledge of the framework
  • No inheritance or mixins (with two exceptions)
  • Domain objects have no knowledge of persistence
  • Separate your “wiring”

The skinniest of controllers

Your controllers should look like this

 class ThingsController
def show
app_of_things.show_thing(rails_adapter)
end def create
app_of_things.create_thing(rails_adapter)
end
end

Nothing more, just that single line. This is an example of where “Tell don’t ask” really shines.

A note on “Tell don’t ask”

As soon as an object’s method returns data back to its caller it relinquishes control of the program.

“Here’s the data, you decide what to do with it.”

In hexagon land the application is in charge until the bitter end it never returns data back to its caller, it sends messages and calls all the shots.

Don’t return anything to controllers

So how does the view or data get rendered? It’s your app’s responsibility to send a message back to the web layer instructing it to render.

The mysterious rails_adapter will be a wrap the Rails controller defining a narrow interface that your app will depend on.

I recommend you implement methods such as #success, #created, #not_updated and map these to redirects or appropriate HTTP status codes in your adapter.

The adapter is not part of your application, it’s the mediator that translates results or events from your application into something Rails can understand. It can and will have knowledge of the web or framework but must not leak it into the application.

The application has no knowledge of the framework

Define your own APIs for everything your application touches, do this by wrapping foreign objects in scar tissue. Use SimpleDegator or Forwardable to make proxy object quickly and easily.

No inheritance or mixins

Predictably I make exceptions for SimpleDegator and Forwardable. The Gang of Four said “Prefer composition over inheritance” so just prefer it, all the time! These two standard library tools will help you build composed objects easily.

Domain objects have no knowledge of persistence

Use a combination of the repository pattern with a simple data mapper to get your data into some PORO or Struct objects.

Writing a general purpose data mappers is hard, Ruby doesn’t have one yet and the enterprise solutions like Hibernate are not exactly loved. My advice is to write your own data mapper without making it general purpose or feature rich. If it only works just enough with your data it shouldn’t be too complex. Add the features as you need them, optimise as lazily as possible.

Separate your wiring (or inject dependencies)

Have an object whose responsibility is to wire up all the others, it will make your code simpler and more flexible. I’ve written and spoke about this before so won’t re-iterate here.

That’s it

That’s my hexagonal prescription. If you want to get in touch to nerd out and discuss these ideas I’d be more than happy to chat.

Where’s the sample app?

In the works :)

架构:Hexagonal Architecture Guidelines for Rails(转载)的更多相关文章

  1. 架构:The Onion Architecture : part 1(洋葱架构:第一篇)(转载)

    原文地址:http://jeffreypalermo.com/blog/the-onion-architecture-part-1/. I've spoken several times about ...

  2. 微内核架构(Microkernel Architecture)

    微内核架构(Microkernel Architecture) 微内核架构有时也被成为插件架构模式(plug-in architecture pattern),通常用于实现基于产品的应用,如Eclip ...

  3. 事件驱动架构 (Event-Driven Architecture,EDA) 简介

    EDA 是一种侧重于以生成/消费为基础的异步通信的架构模式.这主要对照于传统的基于线程的同步系统. EDA 是一种以事件 (event)为核心,提供事件产生,路由,消费已经结果回调等机制的架构模式. ...

  4. 编译器架构Compiler Architecture(下)

    编译器架构Compiler Architecture(下) Combining Scanning and Parsing 实际上没有必要将扫描(词法分析/标记化)与解析(语法分析/树生成)分开.基于P ...

  5. 编译器架构Compiler Architecture(上)

    编译器架构Compiler Architecture(上) 编译器是程序,通常是非常大的程序.它们几乎都有一个基于翻译分析综合模型的结构. CONTENTS Overview • Compiler C ...

  6. 架构:The Onion Architecture : part 2(洋葱架构:第二篇)(转载)

    原位地址:http://jeffreypalermo.com/blog/the-onion-architecture-part-2/. In part 1, I introduced an archi ...

  7. 架构(Architecture)和框架(Framework)杂谈

    1. 架构和框架的设计层次不同       类似于硬件设计,软件设计也分为不同的层次.典型的软件设计层次如下图:        在这个图中我们可以看到,Framework处于Micro-archite ...

  8. ASP.NET Core 企业级开发架构简介及框架汇总 (转载)

    ASP.NET Core 企业开发架构概述 企业开发框架包括垂直方向架构和水平方向架构.垂直方向架构是指一个应用程序的由下到上叠加多层的架构,同时这样的程序又叫整体式程序.水平方向架构是指将大应用分成 ...

  9. 架构(Architecture)随想

    架构(Architecture)的意义: 先不要看什么是架构,先看下architect是什么,没有错,它是建筑师,在一块空地上build高楼大厦的人,它是一个designer,设计好整个大楼,也是一个 ...

随机推荐

  1. JS post提交表单

    js post方式提交表单有两种办法,1:AJAX提交 2:在JS里拼出一个form,然后submit 第二种办法的代码 //这个主要是解决给password MD5 var email = 'ema ...

  2. CF1064B 【Equations of Mathematical Magic】

    题目要求解$a-(a\oplus x)-x=0$的解$x$的个数 移项得$a-x=a\oplus x$ $a$的二进制形式,应该是一个$01$串,异或的过程是不能影响到两个不同的位的,所以我们按位考虑 ...

  3. 【noip模拟赛1】古韵之乞巧 (dp)

    描述 闺女求天女,更阑意未阑. 玉庭开粉席,罗袖捧金盘. 向月穿针易,临风整线难. 不知谁得巧,明旦试相看. ——祖咏<七夕> 女子乞巧,是七夕的重头戏.古时,女子擅长女红被视为一种重要的 ...

  4. 003 jquery层次选择器

    1.介绍 2.程序 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  5. 如何启用内置的Win10 OpenSSH客户端(转)

    如何启用内置的Win10 OpenSSH客户端 关注Windows10,锁定Win10之家(http://www.ghost580.com/windows10/) 如何启用内置的Win10 OpenS ...

  6. 001.hadoop及hbase部署

    一 环境准备 1.1 相关环境 系统:CentOS 7 #CentOS 6.x系列也可参考,转换相关命令即可. hadoop包:hadoop-2.7.0.tar.gz #下载官方地址:http://w ...

  7. Android-RemoteView-桌面小部件

    Android-RemoteView-桌面小部件 学习自 <Android开发艺术探索> https://developer.android.google.cn/guide/topics/ ...

  8. jQuery方法实现

    children 原生JavaScript中,如果希望找到某个元素的子元素,只能通过Node类型上的children方法一步一步获取.如 let li = document.querySelector ...

  9. Winform给TextBox设置默认值(获取焦点后默认值消失)

    主要是通过TextBox的获取焦点Enter和失去焦点Leave两个事件来实现的, 思路如下: 1.设置一个字符串常量,作为TextBox的默认值: 2.在界面的构造方法中将默认值赋值给TextBox ...

  10. 用docker搭建ss访问火星

    最近弄了个vultr的VPS,便想用它搭个梯子访问火星.由于vultr是支持docker的,便找了个ss的docker镜像: https://hub.docker.com/r/mritd/shadow ...