📜 ⬆️ ⬇️

Crossing borders: a case with rails

Ruby on Rails development differs in fundamental positions from Java development. In this article, Bruce Tate describes the main differences he found when using Rails to develop complex, scalable websites from scratch.

Developers on the tracks often look at their fellow coffee lovers as the remnants of the past. And Java devotees often describe Ruby on Rails as a toy that has no place in any serious software development project. As a consultant who has worked intensively with both technologies, I know that the truth lies somewhere in the middle. Since this Crossing Borders series is ending, I would like to make another comparison. Instead of looking at a particular language or technology, I’ll focus on my current project and compare it with the Java projects I’ve worked on in the past. (I take this opportunity to direct you to the previous articles in the Crossing Borders series, which describe the topics covered here in more detail). This article should first let you know what the disadvantages and potential advantages are when using Rails to develop web-based applications.

Business challenge


Neither Ruby on Rails nor Java are the only correct solutions for any problem. To increase the likelihood of success, you need to consider your business problem for a long time and thoroughly, understand the environment and know your team. Only then can you choose a good language to solve your problem.
Last year, Arvando Systems hired me to lead a team that was to develop ChangingThePresent.org , a new product that would help bring donors and non-profit organizations together. Like many Internet companies, we sell clear products that our customers buy. But unlike other companies, “products” represent opportunities (or gifts), such as paying an hour of work for a cancer researcher for $ 50, helping a blind person for $ 30, or protecting an acre of a century-old forest for a month for $ 20.
We had two main challenges: an ambitious plan and a long-term complexity (complexity throughout the project development).
We started development in September and we had to finish development by November in order to get a good profit for the Christmas holidays. (In fact, we were delayed for two weeks). We knew that a Java based solution would take from 6 to 18 months. Productivity was very important. The java solution did not satisfy this requirement.

Considering the challenges posed to us, we knew that we could attract traffic of the order of a million visits per day. We had to cope with hundreds of thousands of hits a day to be successful, so scalability was important. This indicated the use of Java.
')
Finally, we knew that even after the site was launched, everything would just begin. We wanted to start with only 3% of all our plans. Therefore, the technology used by us had to scale both in terms of complexity and in terms of load.

I believed that Ruby — with its capabilities as a high-level language — and Rails — with reduced configuration needs and a simpler, integrated programming model — could scale better in terms of complexity.

But time and scalability worked against us, other factors worked for us. We had an absolutely clean state: we could choose any technology, any team we wanted. We could define a project, a culture, and a complete set of technologies. In general, we had complete freedom of choice.

Java is an excellent general purpose language. He is always oriented towards new features such as embedded systems and mobile devices. Java also succeeds in combining various requirements. It is highly productive, popular and well supported in the market. But, as you saw in this series, Java is not necessarily the best choice for developing Web-based database applications from scratch (see the article “Web development strategies in dynamically typed languages” ).

In contrast, Ruby on Rails is a new framework. Not a lot of people used Rails for sites with high traffic and almost no multi-level development of Rails projects. But, Rails is an extremely productive framework for database-based web applications. Finally, our aggressive schedule led us to choosing Ruby on Rails despite the lack of experience in developing long-term projects on Rails and the presence of large-scale implementations.

As soon as we made a decision, we quickly recruited a talented developer for the project. We also found that our productivity was fantastic - even more than we expected. We had some problems with stability first, so we redoubled our testing efforts (see the articles "Testing in integrated frameworks, Part 1" and part 2 ). Since doubling, we have increased our stability unimaginably.

Philosophy


Each framework developer works with a set of assumptions that create the framework philosophy. Learn how to live with the limitations of this philosophy and you are a happy programmer. Fight them, and you will feel crushed. Rails and Java have completely different philosophies.

Rails is an integrated framework that intensively uses the dynamic nature of Ruby (see the article “What's the secret sauce in Ruby on Rails?” ). Rails developers enhance the framework properties to increase productivity, rather than introduce new tools to support development tools, and often take a simplified look at web architecture, as you have seen in previous articles in this series. Java developers should often put together pieces of their environment, choosing independently the storage system of objects (persistence), the web-system and integrating them. They often rely on development tools to simplify key tasks. Web architecture seems to be more complicated from a development point of view.

Full integration


Java seeks to solve one small problem, such as persistency or view organization, and Rails, an integrated environment.

The advantage for Rails developers is that they don’t have to solve the problem of integrating many essentially different frameworks.

Most Hibernate developers fell into the trap of prematurely breaking the link to Java web frameworks. Rails view frameworks are built from scratch with the expectation of integration with ActiveRecord, a framework for storing Rails objects. You will experience the same feeling when working with Rails frameworks for Web services, configurations, and plug-ins. Java supports many fundamentally different frameworks, with different approaches to integrating all of these things.

The dignity of Java developers is a choice. If you need to build a framework from scratch, you can consider a SQL-based solution for database integration such as iBATIS or one of the many JDBC-based wrapper frameworks for Java. If, on the contrary, you start with your database schema, you can consider ORM frameworks such as Hibernate. If you use Rails you have a single primary choice - ActiveRecord. This means that the Java framework, providing more choice, sometimes provides the best solution for integrating projects. But since we designed the project from scratch, the choice was not a big problem.

Dynamic language


The next major component of the Rails philosophy is a dynamic programming language (see the article “Typing strategies beyond the Java model” ). Java tools seek to effectively use the additional information provided by the Java typing model. Tools can detect errors and effectively restructure or refactor code. Rails also effectively combines the advantages of a programming language. Ruby is the ideal language for creating domain-specific languages ​​(DSL) (see the article "Record and Java programming" ). Rails intensively enforces the use of DSL for everything: from creating relationships between model objects to specifying arbitrary components such as state machines and images uploaded to the server. Dynamic languages ​​are often more comprehensible, which is why Rails projects are much shorter than their Java counterparts, allowing users to write both code and configuration more clearly. At ChangingThePresent.org, we noticed that our top programmers can be more productive and we don’t need to hire programmers with more experience. I'm happy about it.

A typical Java programmer is religiously committed to his IDE and has a good reason. The IDE gives it code hints (code completion),
eliminates common errors and provides an incremental compilation to speed up the coding cycle, compiling, hosting, and testing. In recent years, development environments have begun to use even more information provided by the compilation cycle and static typing. The IDE is currently editing abstract syntax trees instead of or in addition to the textual representation of the code. This strategy allows you to create powerful refactoring tools that are much more difficult to obtain using the same methods for dynamically typed languages.

Static typing allows you to get good development tools, but it has drawbacks. Static typing requires a compiler, and the compilation step can completely destroy productivity. Using Rails, I can change the line of code and restart the browser, immediately seeing the result of the changes. In contrast to Java programmers, most Ruby programmers use only a good text editor. TextMate, the most popular editor for Ruby on Rails, highlights syntax, complements code, and has good template support for commonly used constructs. And the editor is more than enough to write simple Ruby scripts that underlie Rails. Instead of a full-fledged debugger, I use the breakpointer script, which can stop the specified application and send me to the Ruby interpreter, where I can call methods, view the values ​​of variables and even modify the code before continuing.

Simple architecture


A typical Java Web application architecture has a domain level (domain objects), a data access object (data access objects), a facade level that provides a business level API, a controller level, and a view level. This architecture is slightly more complicated than the classical model-view-controller architecture, which was first used in the Smalltalk language. On the contrary, RoR uses one model level, using the ActiveRecord pattern, controller level and view level. We love the Rails approach. It is more understandable and leaves less room for the appearance of additional complexity and errors.

Arrangements (agreements) instead of configuration


Java frameworks often use XML configurations, while rails mostly use arrangements to avoid configurations wherever possible. Where a programmer needs to configure something, Rails relies on Ruby, often in the form of a DSL for configuration. For development from scratch, I find that arrangements instead of configurations make sense. This strategy shortens many lines of code for me and simplifies the code I have to write. We figured out that we are using 1/10 of the configuration that would have to be done in Java. We sometimes lose in flexibility, but not so much that this disadvantage surpasses acquisitions.

Summing up, the philosophy of the rail framework is great for solving the task of creating the changingthepresent.org. The integrated stack allows me to get more functionality from the framework without having to do unnecessary integration myself. The philosophy of the arrangements instead of configuration saves me time. Dynamic language gives my experienced developers more power and flexibility, while at the same time allowing them to express more advanced ideas with less code. The framework is consistent with the abilities of my team as well as with the business problem that we solve.

Persistents


The most popular storage frameworks for Java and Ruby illustrate the difference between the two much better than all other features. Java developers usually use Hibernate. With Hibernate, you take an existing model and an existing schema and set the correspondence between them using annotations or XML. Hibernate classes are POJOs where each object is generated by one common base class. Most configuration is done explicitly using annotations, XML, or a combination of both methods.

ActiveRecord, in contrast, is a wrapper framework, which means that each class wraps around an existing class (see Exploring Active Record ). ActiveRecord automatically adds features to model objects based on the content of the associated table, such as the attributes of each column in the table. All classes inherit from a common base class. ActiveRecord is mainly configured using generally accepted conventions. For example:

The ORM is the best solution when you have a ready-made scheme, perhaps already developed taking into account the object model. But when you develop a database schema explicitly for your application, you often do not need the ORM framework. We see ActiveRecord as a tremendous advantage to us. We can use a relational database using SQL as needed, or remain higher than SQL when it is convenient.

Migrations


Rails migrations allow us to specify differences between the two schema versions and the data they contain in the code (see “Rails migrations” ). Each migration is named and numbered. I can switch from version to version of the scheme at any time.

Migrations have some special advantages, allowing us to:

But migrations have limitations. If two developers create migrations at the same time, the numbers may get confused and we must intervene manually. We minimize these problems by effective communication: team members say when they are building a new model that requires migration. But this model is usually dependent on a small number of developers or affects a small part of the migration.
ActiveRecord has other drawbacks, some of which are intentional. The founders of Rails believe that the constraints (constraints) and compositions are set in the application, not in the database, and this causes a side effect. ActiveRecord does not use views very well: a creation process that clones a schema, copies test data and runs tests does not copy them correctly.
ActiveRecord also has difficulties in some cases with referential integrity, since some types of associations may use more than one database table. Intensive loading of complex models is very complex and often requires SQL when several lines need to be combined. Inheritance is limited: with ActiveRecord, I am forced to use a mapping strategy called singe table inheritance , which is not always optimal.

All object storage strategies are a ball of compromise. I believe that ActveRecord strikes with an effective set of compromises, though it is a sin in terms of simplicity. Thus, ActiveRecord plus migrations are a big plus for us. We can create our solution quickly, and we have enough access to SQL for better performance when needed. But it would be great to use Rails with projects that have ready-made schemes, with which ActiveRecord does not always benefit. Alternative storage models are evolving, including RBatis - the port of the iBATIS Java framework (see resources). But it's too early to say how effective RBatis will be.

Conclusion


For my team and my situation, Ruby on rails was wildly effective. I still do not know how well the project is scaled, since we live only three months. We have just received a substantial increase in traffic. But we know about productivity.
I know that the team went along a path that requires a smaller budget, unlike competing shops offering Java solutions. I am also satisfied with our productivity.

In the Crossing Borders series, I introduced you to languages ​​and solutions outside the scope of Java solutions. Programmers are, after all, artisans. The recruitment of each experienced artisan should contain a wide range of tools that are suitable for each situation. In addition to the tools, the perspective you saw offers new ideas that you can use. Even now, framework developers use techniques from Seaside, Rails, and even from JavaScript to Java frameworks. Look for a chance to do the same to cross borders.

about the author


- Bruce Tate is a father, mountain biker and kayaker from Austin, Texas. Chief Technology Officer (CTO) of WellGood LLC and Chief Architect of ChangingThePresent.org. He is also the author of three Java bestsellers, including Jolt winner Better, Faster, Lighter Java. He recently released From Java to Ruby on Rails: Up and Running. He worked for 13 years at IBM and later formed the consulting firm RapidRed, specializing in lightweight development strategies and architectures based on Ruby and Ruby on Rails.

Source: https://habr.com/ru/post/30996/


All Articles