原文地址: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. tensorflow实现猫狗大战(分类算法)

    本次使用了tensorflow高级API,在规范化网络编程做出了尝试. 第一步:准备好需要的库 tensorflow-gpu  1.8.0 opencv-python     3.3.1 numpy ...

  2. Java基础91 mysql的用户权限设置问题

    1.概述 1)MySQL数据库中root用户具有最高的权限(超级用户),可以对任何数据库,任何表进行操作. 2)权限账户,只拥有部分权限(CRUD) .例如:只能操作某个数据库的某张表等等. 2.my ...

  3. OCR识别-python3.5版

    刚接触,啥子都不会,按着教程走 需求:识别图片中的文字信息环境:windows系统 开发语言:python3.5 使用工具类:1.pyocr 2.PIL 3.tesseract-ocr 步骤: 1.p ...

  4. AC自动机算法学习

    KMP+TRIE int val[1000100][31],tot; int tr[1000100]; int fail[1000100]; struct AC_Trie{ void clean(){ ...

  5. 第三届CCF软件能力认证

    1.门禁系统 问题描述 涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况.每位读者有一个编号,每条记录用读者的编号来表示.给出读者的来访记录,请问每一条记录中的读者是第几次出现. 输入格式 ...

  6. vuejs、eggjs、mqtt

    vuejs.eggjs.mqtt全栈式开发设备管理系统 vuejs.eggjs.mqtt全栈式开发简单设备管理系统 业余时间用eggjs.vuejs开发了一个设备管理系统,通过mqtt协议上传设备数据 ...

  7. 【AtCoder】AGC030

    A - Poisonous Cookies 有毒还吃,有毒吧 #include <bits/stdc++.h> #define fi first #define se second #de ...

  8. Flyweight模式_Java中23种设计模式

    —————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流! —————————— 享元模式: Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用 ...

  9. 【Java】 大话数据结构(8) 串的模式匹配算法(朴素、KMP、改进算法)

    本文根据<大话数据结构>一书,实现了Java版的串的朴素模式匹配算法.KMP模式匹配算法.KMP模式匹配算法的改进算法. 1.朴素的模式匹配算法 为主串和子串分别定义指针i,j. (1)当 ...

  10. 探究 encode 和 decode 的使用问题(Python)

    很多时候在写Python程序的时候都要在头部添加这样一行代码 #coding: utf-8 或者是这样 # -*- coding:utf-8 -*- 等等 这行代码的意思就是设定同一编码格式为utf- ...