Breaking a large rails app into smaller apps?
Modularizing Rails applications
Best practice for structuring a 'large' Rails app
I have a quick question on modularization in a large Ruby on Rails App.
Setup:
I am building a core app that stores information about people. I also have several 'modules' that use that information in very different ways. (e.g. one could display information about the people, another could figure out connections and commonalities between them, etc).
The question:
How do I modularize this app efficiently?
Potential Answers:
Since the modules share models and views with the core app (and eachother) it makes sense for me to combine them into one app. However, as the app grows this will obviously lead to problems. This to me suggests either Namespacing the controllers and models "How to organize controller in moderately large Rails application?" or using engines "Modularizing Rails applications".
Since the modules are in active development it is very helpful to use rails generators on them, which seems to make using Engines a pain in the butt. It also seems that while engines are fully supported from a Rails point of view, they still seem rather hacky with regard to lack of generator support and database migrations. Does anyone have experience with developing engines successfully? It seems like engines would be a great solution if you had a working app and wanted to port it into a plugin (i.e. copy paste code) but if you are actively developing it (changing models etc) it would be difficult.
The last thing I have seen around is using multiple apps and one database. This way seems like a royal pain with migrations and keeping models straight etc etc. But I thought I would get thoughts on that as well.
Rails engines seem to be the correct solution for you. I have used engines when I worked with Refinery CMS, which is built on top of Rails Engines.
The following are some nice links which talks about Rails Engines:
http://www.themodestrubyist.com/2010/03/01/rails-3-plugins---part-1---the-big-picture/
http://www.themodestrubyist.com/2010/03/05/rails-3-plugins---part-2---writing-an-engine/
http://www.themodestrubyist.com/2010/03/16/rails-3-plugins---part-3---rake-tasks-generators-initializers-oh-my/
http://www.themodestrubyist.com/2010/03/22/rails-3-plugins---part-4---more-on-generators/
I wouldn't use engines. Engines are meant to be used to share functionality between apps. What you want to do is not to share functionality but to organise it.
In order to organise your code you can do a lot of things.
Use namespaces.
Keep your controllers thin.
Keep your models thin (Yes, your models; see next bullet point)
Use the Data Context Interaction (DCI) pattern.
Use a widget framework like Apotomo, or Cells.
Write tests, so you can refactor.
Consider a Service Oriented Architecture(Consider Hypermedia API design) if your app's responsability grows too much.
Andrzej has very good articles about DCI.
http://andrzejonsoftware.blogspot.com/2011/08/dci-patterns-how-to-write-dci-contexts.html
One application, one database.
Share the models between the modules.
Namespace your controllers and views.
Test.
You can also use Rack Middleware to handle specific tasks.
For the bulk of your application, Engines seem like the best solution – it's something I'm looking at doing too. Looks like you can define generators in the Engine easily enough.
Depending on the structure of the data, and access patterns, it might be useful to separate the app into multiple apps, and possibly, additionally, provide data access by (RESTful) APIs.
In my experience, this allows for the best structures when your application(s) grow from middle to large size, and forces you to think about structures and separation of concern. Scaling up is also usually easier.
Related
I am just getting started in a Rails project after a long time in the PHP world.
This project is in a very early stage, meaning that is a good time to do major changes, and currently comprises two different rails modules, one for administrators and one for users, both in separate rails instances. What I would like to do is to merge both projects into a single rails instance, which I believe it will improve the manageability of the application in the long run.
Both instances share the same database and each of them has a devise model for authentication. I have been documenting myself about ways of merging both projects and I came up with two alternatives: the first would be to create two namespaces, one for users and another one for admins, and share the model and framework logic. the second one would be to create engines for admins and users, which seems to be cleaner but much more complex.
I have read a lot documentation and I am experimenting with rails, but at this point I am in need of a more experienced opinion.
Thank you in advance, and I appreciate your thoughts on this.
Both namespaces and engines have pros and cons. Which one to use will come down to your particular use case. For the most part, I recommend using namespaces as it tends to be easier and saves some headaches. Especially when sharing a data model. However, engines are great when you want to share common isolated behavior in multiple applications.
Engines
Pros
Isolate related functionality. This is especially good if you have some tables that are only used by one of the engines as they can manage their own database migrations with prefixed table names.
Can be reused in multiple Rails applications. (In some cases)
Good starting point when extracting code out of a monolithic Rails application.
Reduces the chance that developers working on different engines of a large codebase will break functionality in one of the other engines.
Cons
Not a common pattern to have an application that is made up entirely of engines. So it will take new engineers some time to get used to how everything is setup.
Can be frustrating to share common functionality. E.g. stylesheets
You will most likely end up sharing code between the two engines in unexpected ways. Which takes away some value of the Isolate related functionality benefit.
Text editors with Rails plugins tend to have odd behavior. For example, the vim plugin shortcuts sometimes don't work when inside of a plugin directory
Namespaces
Pros
Simple to use and already plenty of Rails conventions to follow.
Sharing assets and other common functionality tends to be very straightforward.
Fully supported by text editor rails plugins.
Cons
Unclear which models or libraries are important to different namespaces.
I have a large rails application with 3 separate 'components'.
One is a mostly static WWW site, one is a shopping cart based on Spree, and one is a reward-program based on Instagram's API.
Currently they are all one giant Rails 4.0 application. As this app has grown over time, I have it harder to make distinctions between components. I want to modularize the app to keep these 3 components separate.
Is there a preferred way to do this "SOA" sort of architecture? or would it be better to turn each 'component' of the app into their own mountable engine? Or is there an even better strategy?
I have been looking at Spree's core, and how they have each component as an engine, and load them in the top level, and I'm thinking this may be the best route.
I don't have any experience with Ruby or Rails, but based on my experience you will need to ask/answer the below question and then decide how you want to proceed forward.
Who's going to be developing the code base and who'll be maintaining it?
If it's just you who's wearing all the hats, you may not want to have the overhead of implementing SOA (web-services to be specific). That said, you should definitely have a 'Contract' between each of these components or modules (however you refer to them). That way your modules/components can evolve independently and changes made to one to make the logic better doesn't necessarily mandate changes to the other components.
If it's you and a couple of other developers, I'd still say that you may not want to take the WS route yet.
If it's different teams that are developing and maintaining these components, then you are taking about an application at enterprise level and then you will start seeing the benefits of SOA (based on WS).
Cheers,
K
We are in the processing of building a new version of our application from the ground up. Our current Rails application, which has been in production for 5 years and has 100 models. I am considering ways to simplify the codebase for the next version.
I can see Reporting Features and Admin Features being broken out. Most everything in the application in Product-based though. Even breaking out the Reporting, I would have to duplicate models, which is obviously not suboptimal.
I am aware of Rails Engines, I am just not certain if that feature is as robust as it should be. Another concern is designing this application based on Rails 3.2 when Rails 4 is already in beta.
I'm not looking for this to be an opinion piece, I was just curious to see if there was a convention for breaking out modules vs. building an all-encompassing application. The convention either exists in the community or it doesn't. Thanks for any guidance you can offer.
I would have to duplicate models...
You might consider moving the models into a gem, and including the gem in each application.
The convention is generally:
Build as one application
Have the classes know as little as possible about other classes
Extract when it hurts
Extracting to either engines or to services (service-oriented-architecture) is a decision for your scalability requirements.
For the first time I'm creating a quite complex Rails app.
I'd like to know what's the best way to organize that app by folders. Until now, I'd do everything under one app (all the models, controllers, etC) but reading some open source code I realize that they put everything under different apps.
Like for example Spree Commerce. They have a general folder and inside that they have different apps (API, core, admin, etc). How is that done and is that the best way to do it?
I'd like to get pointed to the best way to do it (a book, blog, anything) so I can understand how I can architect my app for future maintenance.
thank you
As an aside I think the title of your question is a little confusing. Rails, by using convention over configuration, defines 'how to organise a Rails app'. I think your question is rather about how to architect your application as opposed to anything Rails-specific. Maybe tweak the title?
That aside, without knowing any more detail about your project it's a tricky question to answer, but I'll give it a go.
All applications should start off simple, if you believe (like I do) that you should start by building the simplest thing that could possibly work. Given this, since you're using Rails, then in all likelihood the simplest thing would be to structure your app as a vanilla Rails 3 application. This will probably (I say 'probably' because I don't know any specifics about the app) allow you to get a beta version of your app up and running pretty quickly without worrying about complexities which at this stage in the development of your project are not a problem.
If you need to create an XML or JSON-based API then Rails makes this really easy using the standard framework, which will allow you to spend more time thinking about the API design than how to code it, and it's the API design which is the most important thing to get right in the first instance.
Similarly, your Admin site can be part of the same app just in a different namespace. If you find later down the line that you want it as a separate app, you can do this (maybe you could use the awesome API you designed to facilitate this), but why bother designing it with this added complexity (and hence extended development time) in the first place if you don't have a good reason for doing so?
Once you have your app up and running and people are starting to use it, you start to get a picture of where the bottlenecks are and where the design could be improved. At this stage, if there's a need, you can start to move parts of the app to scalable solutions, such as running your API as a standalone service, introducing caching, changing data stores and other improvements and optimisations.
Even if your app is as wildly successful (and I hope it is!) then re-architecting your application whist continuing to run the existing service is still entirely possible, as Twitter have proved. Just stick to Knuth's statement and you'll be alright.
Regarding reading material, that's a tricky one. For me a lot of the XP and agile development classics taught me a huge amount about how to approach program and app design. I'd also check this StackOverflow topic for book inspiration.
Good luck!
Spree uses Rails' Railties (Rails::Engines). Railties are introduced in Rails 3 to make it more modular and easy to extend. Rails 3 itself is a collection of Railties (ActiveSupport, ActiveModel, ActiveRecord, etc.).
If you are developing a complex app I would suggest spending some time planing its' architecture. Designing a complex app without any initial planning would definitely end with a maintenance nightmare down the road. It also introduces a huge learning curve for the new team members, slow down your new feature introduction and of course, frustration.
Anyway, don't over optimize, but don't forget to design your architecture for your needs.
IMHO, I will create very complex projects as one app. I have reason to believe that Spree and Radiant build under seperate apps so that under the pretense of their open source communities, contributors can contribute code easily without tampering with the core data, and the core workings of the application.
Otherwise, you should be alright just building it as one app. Just keep it neat.
Here is what have kept me sane for several years of RoR development:
I use Rails Engines, but keep them in same codebase as the main app. Here is good starter for modular Rails app:
https://github.com/shageman/the_next_big_thing
Wherever I can I try to reduce coupling and use composition to make things easily testable, reusable and maintainable. This helps to eventually extract module or engine as separate gem. Composition is done by routes (mounting), directory overlaying (assets), dependency injection or configuration.
If I don't need to re-use an engine I put it in the same code base as the main app which is single deployment unit. Thanks to that I don't need to switch between projects in my IDE. While in development environment any changes to the engine code are instantly picked up by Rails reload mechanism.
What are the most common tasks for Rails applications? I mean, for example, for small and simple sites people usually choose PHP, because it's really easy to maintain and to deploy, most hosting platforms support all your needs. But I'm interested what people usually produce with Rails. What kind of applications?
Pretty much the deal is, if your app would benefit from object-oriented design, Rails would do well. If your app would not benefit from object-oriented design, Rails would not.
The framework revolves around a relational object model, storing items in a database (e.g. posts belong to users). For large apps that have that sort of structure, Rails makes the development process easy (relatively). Running anything else with Rails, though, would be far too much overhead to be worthwhile.
So, say you have a one-function website, e.g. take input and encrypt to MD5, SHA-1, and other forms of encryption. Using Rails would be pointless. You can still use other Ruby-based frameworks if you just like Ruby, but Rails would not be the right choice - and I'd probably recommend PHP, since it does well at simple scripts.
You should check out Ruby on Rails: Applications.
Mostly large applications, that benefit from the MVC pattern, and don't get drowned by the overhead of such a large framework.
www.basecamphq.com and www.github.com are good examples.
With the advent of phusion passenger I think using rails can be warranted in almost every case if you like developing with it. The deployment overhead has gotten very small and the development overhead does not exists if you are used to the framework.
Check out 37Signals who has developed Rails and use it in their products.
It sounds like you're asking "what framework/language should I use to make a website?" There's no one perfect answer to that, as a good answer will depend heavily on your knowledge, experience, place of employment, and the audience for which the site is designed.
That being said, Ruby on Rails is a good choice, and there are several benefits to using it:
it has a large base of users, so that your questions can be answered on sites like StackOverflow.
it's being actively developed, and there are many tools for it that are designed to help you be productive.
it simplifies interactions between your web site and your database using an object model.
it allows you to easily describe the dependencies between various aspects of your application.
it's not PHP. :)