The whole idea of having a data-structure that you retrieve from the database and carry through all the layers to the UI makes the development very quick at the beginning.
The coupling it provides, at the later stages of development makes it very difficult to split the app into any kind of modules. It's also difficult to test anything in isolation. That's why Cucumber, Capybara, Selenium are so popular, as they help you in writing integrated tests.
Integrated tests have their place, but it's impossible to test everything through all the layers. This results in slow builds - a typical syndrome in Rails projects.
The Rails way makes sense for smaller projects. What I'm disagreeing with is using "The Rails way" in bigger, serious projects.
The Rails itself has nothing inherently wrong. I'm not attacking Rails, I'm only attacking 'the Rails way'. You can use Rails for bigger projects, if you know what you're doing.
Tuesday, October 8, 2013
Autor: Andrzej Krzywda o 8:59 PM
Monday, October 7, 2013
It's now the 4th time, I'm teaching the Rails class at the University of Wroclaw. The main goal of this class to prepare people to work in a Rails-based company. The students are the best of the best, so the goals can be high.
Every year, I introduce some changes to the program of teaching to reflect better what is happening in the Rails community.
This year I'm going to focus more than before on the integration with mobile, native apps and on the art of dealing with legacy projects.
We start with extremely quick Ruby lessons, based on the Ruby koans exercises (students do it on their own).
The first 3 lessons are about "the Rails way", which I make it clear - is good only for toy projects. This is where I teach about ActiveRecord-oriented programming, coupling everything with everything, making things impossible to test - you know, the usual Rails stuff.
Once we know the enemy and know the pains it provides, we learn how to avoid that.
This is where good, solid OOP lessons come in, service objects, repositories, domain objects, etc.
After that, we enter the "frontend" module. We learn how to create Single Page Apps using the dominant JS frameworks (Angular) and some no-framework techniques (HexagonalJS. This also includes techniques like Pusher to have server->client communication possible.
We also talk a lot about the way, a Rails backend can expose data through the API to the JS or mobile app clients. Mobile apps will take more time this way, as I want to show how to best cooperate with mobile developers.
There's a lesson about proper Rails deployment, things like Chef, Jenkins, Continuous Deployment etc.
Throughout the class, we'll not only create new Rails apps (lots of them), but I also want to teach how to find yourself in a legacy codebases, like Redmine or Discourse, how to refactor out from the mess, fix bugs, add new features - that's probably the hardest part of the class.
Testing is an ongoing topic in the class, as well. We'll learn about unit testing of different layers, integrated tests and their pains.
I hope it will be fun, as always :)
Autor: Andrzej Krzywda o 10:33 PM
Monday, July 8, 2013
- maintaining created_at and updated_at
- displaying errors
- displaying flash messages
- redirects between pages
- sending emails
- attr_accessible/attr_protected (security)
- CSRF - security
Autor: Andrzej Krzywda o 8:10 AM
Sunday, June 23, 2013
In the previous post, I highlighted the typical Rails bugs, that I encountered during my research on better ways of working on Rails apps. The bugs were often security-related:
The main common point of the bugs is the ActiveRecord overdose.
ActiveRecord overdose is a surprisingly popular pattern that includes:
- putting everything into the model class
- fear of adding new non-AR classes
- over-relying on convention over configuration
- business logic
- view object
- form object
The Rails-way ActiveRecord is an enhanced version of the original Active Record pattern. The original pattern assumed only persistence and some simple business logic. The Rails version extended it with the view/form responsibilities. In many cases it's also extended with the adapters.
- queries - scopes
- simple validations
- business logic
- tracking changes (touch)
- complex validations
- some callbacks
- factories methods (class methods)
- service (coordinating multiple adapters)
- external api
- exception tracker
- metrics tracker
- image storage
- view object
- first_name + last_name
- http boundary details (urls)
- form object
- acts_as_foo (persistence, logic, validations)
The core responsibility of an ActiveRecord model is being a representation of a db record. That means handling the persistence and having the basic logic. This usually works great in typical CRUD apps. Once things get more complex, it's time to reconsider the active record pattern.
Autor: Andrzej Krzywda o 12:36 PM
Monday, June 17, 2013
As part of my research on improving Rails application, I noticed a pattern in the bugs that are quite characteristic to Rails in several applications.
They have certain 'visible' things in common:
- often security related, like leaking some information to unauthorized users
- they live somewhere in the area of business logic/persistence
- they are not so easy to fix in the existing codebase
- they tend to exist in groups, similar bugs in different areas
- they are easy to miss
- often they appear during the requirements changes
- validations, which often turn into conditional validations
- Single Table Inheritance
- models callbacks
- virtual attributes
- external gems that provide value magically, by using ActiveRecord (implicit dependencies)
Quite a problem as I unfortunately found out.
2. Non-authenticated users see private topics in 404 page
The 404 page should not show private topics.
3. Auto-suggest topics shows private topics
We've got Discourse running with private categories. When a user without access to the private categories type a new topic, they are presented with topics in categories to which they don't have access.
Comment: Did you notice the pattern here?
Accidentally, I've had a small conversation at HN with one of the Discourse founders. He said:
Those private topic bugs are not the result of ActiveRecord. We added a group layer on top of existing code and missed some places where queries did not respect it.
Had we used raw SQL instead of an ORM we would have had the same issues. All projects are open to this style of bug. The correct thing to do is report, close them quickly and add tests to prevent them from happening again (which we do.)
Fix wrong discount calculation with flat percent promotions when there are more than one line item in the order.
This error happened because the order instance here:
is not always the same instance in memory here:
Adding the inverse option to the relationship makes sure you have the same object instance in both places.
When kaminary determines the total count of records it runs the following code
@collection.except(:offset, :limit, :order).count
The issue is that this sequence loads entire dataset to determine the count. This makes heavy load when products have large number of items.
The reason of this behaviour is group_by_products_id here https://github.com/spree/spree/blob/1-2-stable/core/app/controllers/spree/admin/products_controller.rb#L94
Autor: Andrzej Krzywda o 10:09 AM
Sunday, April 28, 2013
During the last wroc_love.rb conference we've organised a "fight" between 4 different approaches to Single Page Applications. Below is the video (0.5h) and a very short and simplified transcript from this event.
The participants, from the left-side:
Patrick Mulder - Backbone
Piotr Sarnacki - Ember
Andrzej Krzywda (me) - Hexagonal
Adam Pohorecki - Angular
moderator - Jan Filipowski
Andrzej: for all the apps
Adam: we need better tools on the backend in order to have a better developer experience
Piotr: Andrzej, would you write wikipedia as a SPA?
Adam: What about SEO?
Andrzej: It's a myth that SPAs are not indexable. Google has an official document for that. It is additional work.
Patrick: You can use PhantomJS for SEO.
Adam: We've used PhantomJS for that, took a couple of hours.
Patrick: Backbone, very small, minimal. you don't bring too much dependencies. you can choose what you want.
Adam: Angular, Two-way data binding is the key feature. Synchronization of HTML and your JS. Choose framework with data-binding. Ember is essentially a language, forces its own object model. Backbone as well. Hexagonal or Angular is pure JS.Your application can live outside of Angular.You could use Angular with a Hexagonal app. Backed by Google, more mature than Ember.
Andrzej: Data binding is not as important as you may think. Manual control is not that difficult. Hexagonal doesn't have data binding jilt-in. Apps are not about data changes, but about actions
Piotr: I agree that data binding is important. Both, Angular and Ember are good for big applications. Nested views, zombie views (backbone). Angular has its own compiler for DOM elements. You need to know how the compiler works. Angular uses dirty checking. Angular claims that your UI shouldn't have than 2000 elements. You're screwed if you have more.
Adam: We built a 100 rows, 500 columns table. We managed to do it with Angular. It's not that hard to do the UI part. Directives are like helpers for html.
Andrzej: It's a problem of all of us here, including Hexagonal. We use different terminology for different things. All the frameworks are far from being Rails, we're not mature enough. All the frameworks are in their infancy years.
Patrick: It's easy to work with Rails and Backbone
Piotr: Ember has its own class model. It's done mainly for making it easy to optimise. Ember is about Convention over Congifuration. Rails in JS. Ember is like Rails, Backbone is like Sinatra. At some point you have to use more plugins if you start with something minimal. A lot of pain if you want to write a big app with a small framework.
Andrzej: I disagree. I would use a framework for a prototype or for a small app. Once the app grows, it has its own world. I don't want the framework to go into my way. I want to have the control over the applications. I'd use Ember for smaller apps, not for bigger apps.
Andrzej: Hexagonal has just started. It got the name just recently. We've used it for over a year. We have a strong team behind it. Our goal is to show the guidelines.
Piotr: Ember is 1.0RC now. Docs are better now. IRC is very active. Google Group.
If you're interested in Single Page Apps, you may want to follow me on Twitter.
Autor: Andrzej Krzywda o 10:00 AM
Saturday, February 23, 2013
Some projects take a long time to develop. In different contexts, the definition of "long" may vary. It was always interesting to me, what are the reasons for it. Recently, though, it became my obsession.
I've started collecting some thoughts on this topic.
Ask yourself and your teammates about the last project you've been working on. "Would we be able to implement the same result in 1 month? In 1 week?".
Surprisingly often, I'm answering to myself - yes, that would be possible, given some assumption. I've had similar answers from my colleagues.
Where does it come from?
Is it the known tendency to underestimating a problem by developers? I don't think so, as we're talking about a project, that has already happened. We know what is to be done. We are aware of edge cases.
"This is time it will be different, faster"
This is another popular trend among us, developers. Most of us are optimistic, even the experienced ones. It's not some kind of a student-syndrome (I'll do it tonight), but a well-thought statement. Is it really different and faster? Not always…
Where does this optimism come from? Good developers become better at solving technical problems. With each problem solved, we know that we solved the problem forever. We love solving problems, every day we're smarter by this attitude. We're progressing and the optimism may come from that.
It's almost impossible to get a second chance of working on the same project. What would that even mean from a business perspective? We rarely get that chance.
Is it the technology that let us think, that we could do better this time? That's a serious candidate. Every time, I switched to better technologies or to better architectures, I noticed the speed increase. I was more confident. I saw the results.
I remember a situation, back in 2004/2005. I was involved in preparing an estimate for a new project. The estimate was about 6 months for 4 developers (assuming ASP.NET). Very shortly after that I learnt Rails. I realised, that the project is perfect for Rails. It was a CRUD-based web app. I kept convincing the management to give it a try. No luck. Finally, I had a chance of coding live in front of some managers. I implemented the main path in about 1 hour (I was well prepared). That convinced them. We've finished this project in 1.5 month, with one junior programmer and me being mostly a PM and a Rails mentor.
What's the lesson? It's hard to tell. I'm not trying to say that only Rails was the reason. Motivation? The passion behind it? Trying to prove something? The focus? I think it was a combination of all of the above aspects.
Is it easy to repeat those aspects? Do they sound familiar?
Have you ever attended a hackathon?
There are many kinds of hackathons. What's most important in this context, is how much can be done in a very limited time. If you look at the results of Rails Rumble, some of the apps are quite big. Many features, everything is polished.
Hackathons are proves that we are able to develop apps quickly.
How can we apply hackathon lessons to our every-day projects? Is it possible?
What else can help us developing software faster?
I would love to know your opinions.
Autor: Andrzej Krzywda o 4:36 PM