8 ms·
Hexagonal Architecture Guidelines For Rails
- styluss 13y ago"Any problem in computer science can be solved with another level of indirection."
- userbinator 13y ago...including the lack of people buying faster hardware. ;)
- RyanZAG 13y agoSlowly but surely re-implementing enterprise java in rails...
- ac2u 13y agoThis is a really lazy complaint that gets reiterated when this approach is mentioned. There's no elaboration here to provide substance to the argument. When I think stereotypical enterprise java complaints, I think people joking about AbstractFactorySingetonProxyBeanAdapterFacadeConcrete. Not this. Whether you agree with the approach or not, it's fair to say that the author is simply drawing some boundaries around his/her business logic to make it framework agnostic, decoupled, and test-speed friendly.
- gtramont 13y agoCouldn't agree more.
- deleted 13y ago[deleted]
- adamors 13y agoAre you really this afraid of software architecture, that anything that goes beyond simple MVC is enterprise java?
- RyanZAG 13y agoOh, no I have no problem with enterprise Java - it was merely an observation. Enterprise Java exists because it works, after all. I just find it interesting that most software projects will eventually come to the same conclusions regardless of their original source.
- adamors 13y agoI'm not talking about enterprise Java. Why do you equate something more complex than an MVC pattern to enterprise Java immediately?
- dragonwriter 13y agoActual hexagonal design is useful software architecture. It may just be extremely poor presentation, but I am far from convinced that the dictates in the article, or the very little bit of very abstract sample code it provides, reflect useful architecture (Hexagonal or otherwise) -- certainly, its not a presentation that fosters understanding and intelligent application over cargo-culting.
- dasil003 13y agoThe hallmark of enterprise java is the incidental complexity needed to implement a given abstract architecture due mostly to the strict limitations of the core language. Ruby's more powerful system allows you to implement architectures with an order of magnitude less ceremony (and some would argue safety) and without as much careful planning required to make sure every possible hook is in place up front. In the end, "enterprise ruby" architectures bear so little resemblance to enterprise java that the comparison is nonsensical.
- matdes 13y agoabsolutely absolutely this. Patterns don't suck. Implementing patterns in Java sucks. Ruby's got a lot of fantastic things going for it, and duck typing means you don't have all the ceremony of defining and implementing interfaces.
- camus2 13y agowell, JEE works but it's not pragmatic. Rails brought pragmatism and good developper experience to all other web plateforms. And Ruby is still a very pleasant language to write. At the end of the day your product is your app running or not,it doesnt matter own much design pattern you implemented in your code.That's pragmatism.
- gregors 13y agoExactly what I thought!
- programminggeek 13y agoThere is a lot that Java EE got wrong, but there is a lot in there that is probably more good than bad. The amount of ceremony and effort (and XML) required to get a basic Java EE thing is not great. But, when I used Play Framework 1.x with Java, it was quite enjoyable. I haven't used it much since, but I could see something like Play solving most of the annoyances of Java EE, while keeping some of the good parts of Java or other JVM languages.
- jhuckestein 13y agoAt that point, I wonder what the benefit of using rails is? Rails shines most when you do things as intended. Even though I wouldn't have designed rails the way it is (remote forms and .js.erb views anyone?), it works really well for a large class of applications. Of course you may eventually hit a wall, but that happens when software outgrows it's original requirements. That doesn't mean you have to build a system for millions of concurrent users from day one. Especially not, when you're making accounting software or a crm or some other run-off-the-mill webapp. In my experience, rails "improvements" are often suggested, when a developer is faced with a large mudball of a rails application that doesn't do things according to convention. This can quickly happen, because rails is deceptively easy to learn. Many developers I know (myself included), started writing a serious app in Rails, without learning a lot about it. Heck, if you're a rails developer and honest with yourself, you probably didn't even read all of the rails guides. In addition to that, I recommend reading a book such as "The Rails Way" front to cover, joining the mailing list, following the core team's blogs and potentially even going through the code. I also DON'T recommend taking your patterns from random blog posts or stack overflow. Rails is very well documented and you can generally find what you need in the docs. As infuriatingly dismissive as his tone sometimes is, I've actually found it best to follow dhh's advice. Not only because I generally agree with it, but also because it's likely to be the best supported design in future rails versions.
- sanderjd 13y agoThere are a few ways to answer the (definitely relevant) question of "if you're doing things this way, what does rails give you?" In some cases, the answer is "nothing", and people really just want sinatra if they really like ruby, or one of the many lighter-weight libraries that other languages have. In some cases, the answer is "actionpack is still really good at what it does, even if it's just used as an HTTP adapter". In some cases, the answer is "activerecord is a really nice ORM". Etc. But I think in most cases, it's because there are just lots of libraries written for rails, and using sinatra or padrino (last I looked) tends to result in re-writing some things that you would otherwise get for free. Although sometimes in order to use those libraries you need to be doing things "the rails way" anyway.
- matthewmacleod 13y agoWhy would you do this? If you're operating at the level where you need this level of indirection, then you should be looking at SOA anyway. Rails is not an appropriate platform, regardless of how much architecture you add to it. If you're not operating there, then you are introducing complexity for no reason, and failing to take advantage of the features that Rails offers.
- bestie 13y agoHaving the indirection there allows you to take the Rails features you want with your boundary clearly defining which ones you depend on. You could start with Rails, get ActiveRecord querying, migrations and template rendering for free and then maybe swap it out for Sinatra and the Sequel gem (I have actually done this). Knowing your where your dependencies and technical debts are is very empowering.
- binarysoul 13y agoWhat does hexagonal mean?
- dcuthbertson 13y agoIt's a reference to Alistair Cockburn's "Ports and Adapters" pattern, also called "Hexagonal Architecture".[1] The only reason I ever heard of it is that it was mentioned in the book "Growing Object-Oriented Software, Guided by Tests", by Steve Freeman and Nat Pryce (a good book in my opinion). [1] http://alistair.cockburn.us/Hexagonal+architecture http://alistair.cockburn.us/Hexagonal+architecture
- dasil003 13y agoWell Rails is a solid full-stack framework that is fairly modular, and of course ruby is extremely flexible in the architectural choices it allows, so it's very easy to take Rails in different directions by instituting your own conventions. It's probably easier to do this then to either pick a minimalist framework like Sinatra and build everything up from scratch, or find another language with a framework that suits your exact preferences. I totally agree that Rails defaults hit a certain sweet spot. Putting a bit of logic in the controllers is fine in most apps, ActiveRecord is intended to mix persistence and business logic because many models aren't complex enough to merit separating them. Starting with a Hexagonal approach may well be premature optimization. I get it. But lets be careful not to throw the baby out with the bath water. Rails intelligent defaults do have a tendency to leave a vacuum for apps reaching a certain level of complexity. That doesn't mean Rails isn't still useful, but just that it becomes inelegant when you don't have any conventions to deal with this and start hacking ad-hoc solutions into your codebase. I have a sneaking suspicion that partially this is inevitable in any living codebase, and that a complex system almost by definition can not be consistent and elegant since it is inevitably built over time under changing conditions. But in any case, I think Rails is a perfectly good place to experiment with ideas for managing complexity in a sizable app.
- patio11 13y agoThis feels like it would be the sort of architectural decision which would be well-served by saying "Here is the app motivating this stunning architectural purity. You will note that this app both exists and was more complicated than the 5 Minute Build-A-Blog demo." Otherwise it's "Rails Project Day 1: Scratch-build a stripped-down ORM. Day 59: That might have been a bit more involved than I expected."
- nimblegorilla 13y agoMost developers using this type of architecture are working on projects for clients that wouldn't appreciate having their code slapped up on pingpongwithdhh.com I agree with the article that rails controllers should not contain business logic. I disagree that writing another ORM layer is a good idea.
- ryanbrunner 13y agoThere's a difference between "controllers should not contain business logic" and "controllers must be one line". There's plenty of sane responsibilities for controllers that don't directly involve business logic - mapping request parameters to something the business layer understands, coordinating view mapping, applying decorators to models, authentication, authorization, etc. By rigidly applying an inane rule like "you can only have one line per controller action", you're going to end up just re-implementing controllers, and leaving your controllers doing nothing but pointless indirection.
- tomblomfield 13y agoI agree with this. Statements like "you can only have one line per controller action" are just dogma. What's the point of a controller? I also don't like ceding control-flow from the controller into the application by injecting the controller context in the form of "rails_adapter", in the name of "Tell, don't ask". It seems like a misunderstanding of the principle. "As the caller, you should not be making decisions based on the state of the called object that result in you then changing the state of the object. The logic you are implementing is probably the called object’s responsibility, not yours."[1] Say you have a module that performs some complex business logic: ShipOrder.perform(args). It's responsibility might be to ensure the right items are combined into a package and shipped. It might write some logging data to an injected logging object. It might tell a label-printing to output the right address label. Ultimately, it should succeed or fail, and pass that information back to the caller. The controller's responsibility, on the other hand, is to direct the control-flow of the request and pass data between models & views (and your other non-model POROs). That's its core responsibility. Passing the controller context into your application object so the application can call-back methods on the controller just seems like a recipe for spaghetti code. It also means you can't use this object on its own, or composed with other objects, without implementing a complex caller-object that you can pass in to receive the callbacks. If the object just returns success/failure, and exposes a limited API so you can access its internal state if required, it becomes straightforward to re-use & compose the object in places outside the confines of your controller. 1. http://pragprog.com/articles/tell-dont-ask http://pragprog.com/articles/tell-dont-ask
- carsonreinke 13y ago"My advice is to write your own data mapper", noooooooooooo
- flevours 13y agoI'd reword data as in "create a clear boundary between your models and the ORM/ODM you use", which easily translates into defining class methods on the model which use the underlying ORM/ODM of choice.
- bestie 13y agoI think this is a really good point, there is a huge difference between trivial data mapping and what an ORM does. Wait while I make this edit ....
- danso 13y agoIt's worth posting DHH's recent interjection into the architecture debate... https://news.ycombinator.com/item?id=7335211 https://news.ycombinator.com/item?id=7335211 tl;dr show some actual working implementation of this paradigm that exemplifies its benefits over standard Rails > Anyway, the invitation stands. Present any piece of real code and we can ping pong on it. I enjoy talking about specifics and improving real code. I detest "oh that was just a poor example, but the general principle is..." kind of debates. If you can't produce a good example, you don't have a general principle.
- lnanek2 13y agoYeah, this original post doesn't have sample at the end, heh.
- lewispollard 13y agoOff topic, but how did you come up with the name for the blog? I ask because there's an awesome record label in my city called the audacious art experiment... wonder if they're related
- bestie 13y agoIt is no co-incidence :) Ben Lane, the founder of The Audacious Art Experiment was one of my closest friends growing up, we were also in a band together.
- lewispollard 13y agoAmazing! I'll make sure to follow your blog :)
- mattgreenrocks 13y agoWeb devs hate him for suggesting that programming technique is important! No, really, perhaps it is worth giving this a try, if only as a means of deliberate practice? You don't get better at programming by plugging in HN's coolest, most fashionable framework, you get better at it by shipping, maintaining, and learning to feel the impact of design decisions. Don't complain you have too much to do, this is building foundational skills that are language agnostic and will outlive Ruby on Rails. Isn't that way more important than pulling up Twitter several times today?
- bestie 13y agoWebby Rails types do often get very aggressive towards this kind of thinking. The point you made about this out-living Rails is a very good one. I'd be coding like this in any language with any framework, Ruby just makes writing SOLID code easy.
- mattgreenrocks 13y agoYou can't rely on industry to teach you what you need to know. They'll put you on endless treadmills learning hackneyed DSLs fueled by hype cycles. Fact is, Rails is almost entirely composed of patterns from PoEAA, along with DHH's excellent taste. At some point, you need to read and apply those patterns yourself to really understand them. Actually, now that I think about it, you're almost much better off self-teaching once you get to a certain competency level.
- lnanek2 13y ago> Where’s the sample app? > In the works :) Considering he says people should write their own data mapper, it doesn't surprise me he is so far behind everyone else he can't even turn out a sample. You can spend many years writing that alone.
- acallaghan 13y agoI'm assuming that the apps that have already been developed with this architecture have been closed source, and he's just waiting to develop an open source demo app, not that he's unproductive as a developer.
- bestie 13y agoUnfortunately they have all been closed source thus far. The problem with writing good code samples is that it requires a lot of time and thought. This was very much an MVP blog post and appears demand for the sample app / code snippets is very real so I will do my best to get something together. Isn't more fun to spend all your time arguing on HN though? :)
- reedlaw 13y agoI feel much of the negative reaction to posts like these fails to grasp the main idea. My take is that you can use other architectural patterns than MVC and still benefit from Rails. In fact, you can use patterns that complement MVC. There is no conflict. Why ignore the history of design patterns and try to squeeze everything into an MVC-shaped box?
- dragonwriter 13y ago> I feel much of the negative reaction to posts like these fails to grasp the main idea. I feel much of my negative reaction to this post and those like it -- and I am familiar with hexagon/ports-and-adapters architecture -- is failure to clearly present a main idea, or even to connect the dictates in the post to the subject in the headline. > My take is that you can use other architectural patterns than MVC and still benefit from Rails. Certainly, the article seems to be trying to use Rails MVC structure to force the design of the web-facing adapter in a hexagonal architecture into an MVC design, what it really fails to do is justify this as a good thing to do (either in general for building an application, or starting from the assumption that we should use a hexagonal architecture, or starting from the assumption that we should use Rails.)
- jlebrech 13y agowhy not abandon controllers at this point and route directly to show_thing?
- bestie 13y agoRoute directly how? Write my own HTTP layer? It's so easy to take advantage of Rails' routing and view rendering.
- grey-area 13y agoRoute directly how? Well, instead of fighting rails, you could just use the lower level stuff it is based on which does the bits you want: Routing - https://github.com/rack/rack https://github.com/rack/rack Templates - http://www.ruby-doc.org/stdlib-2.1.1/libdoc/erb/rdoc/ERB.html http://www.ruby-doc.org/stdlib-2.1.1/libdoc/erb/rdoc/ERB.htm... Rails adds quite a lot of overhead and complexity, not to mention memory usage, so if you're going to bypass most of it, it might be better to start with something more bare-bones?
- thealmightyis 13y agoI agree with that, bringing rails in is like bringing a chainsaw to cut a twig sometimes... The point here is not to look at the devise/router serving http but the porting of the data & business logic to an adaptable, multi-purposed api that is not tied down to the infrastructure in any way. I've used this approach within a Sinatra driven app, CTO said i need to use Rails now for some other thing, a few hours to make the switch, not rewrite the whole thing.
- al2o3cr 13y ago"Where’s the sample app? In the works." ARE YOU GETTING ENOUGH OXYGEN, architecture astronauts?
- programminggeek 13y agoThis is a troll, but holy moly did it make me laugh. Well played.
- bestie 13y ago+1 :)
- tjstankus 13y agoGuilty as charged. :) I'm super-interested in seeing a sample app, particularly the rails_adapter.
- programminggeek 13y agoObvious Architecture (http://obvious.retromocha.com/ http://obvious.retromocha.com/) was heavily inspired by Hexagonal Architecture and even has a working example app: https://github.com/RetroMocha/obvious_status/ https://github.com/RetroMocha/obvious_status/ For the record, with this kind of architecture, you can take the same codebase and use it for a web api, standard rails app, sinatra anything, desktop app, mobile app, or command line app. All using mysql, sqlite, postgres, mongodb, json files, or just about anything else you want for persistence. And your tests should all run in less than a second. It's pretty sweet from a purely technical standpoint. Obvious Status has done that with ruby, but I could see the same thing being done in Java, C#, or even C++. I'm not sure why all the rails people are blogging about this kind of architecture seemingly all at once, but it's not new. It's pretty much where you end up when your standard MVC codebase gets out of hand on a reasonably complex project. Uncle Bob spoke over 2 years ago at Ruby Midwest about this and has blogged about it since then. Obvious came out last January and there were a few people talking about it since then, but not many. The real struggle with this kind of structure is that it goes against the standard Rails patterns and ecosystem. DHH doesn't like it and frankly he's right. It goes against the whole spirit of Rails. It doesn't fit in with Rails. Sidenote, DHH originally called it the worst code he's ever seen attached to Rails, so it's got that going for it. If you go down the path of clean architecture (in any of its forms), you are going to have to convince your team of Rails devs to stop using Rails as they know it. Most Ruby or Rails devs don't want or see the need for this kind of structure. That is okay. We had to build a lot of things to make building Obvious apps in Ruby more awesome, but it's an uphill battle. Other languages give you things like interfaces and method parameter type checking as part of the language and will even check them at compile time. Clean Architecture is great, but I think it's going to lead developers away from Ruby and Rails, at least for the core API portion of their app. I really don't know what language most developers will land on, but it will probably have a compiler, it will probably support functional programming and immutability, it might support OOP, and it will probably be on the JVM. That's just my guess.
- pothibo 13y agoThe problem with this is that he's building an API on top of something he doesn't understand. There's no way you can look at this and think it's a good idea if you have any understanding of how rails works. When I first read this post, I thought the guy was trolling, seriously.
- thealmightyis 13y agothis comment is trolling.
- dragonwriter 13y agoThis, to be evaluated, desperately needs more realistic examples, as well as much better discussion of how the rules relate to the principles of Hexagonal architecture, and what benefit they provide in that context. As it is, I can, with some effort, find some justification for some of the rules in the context of Hexagonal architecture, but as presented its not immediately clear even what part of Hexagonal architecture the various elements are relating to. Perhaps most importantly, it needs to clarify what the application itself and the "rails adapter" look like here.