Slide 1

Slide 1 text

Refactoring on Rails by @makaroni4 Hi! My name is Anatoli Makarevich!

Slide 2

Slide 2 text

I am a ruby developer at http://evrone.ru And I work for Evrone.com – russian company that is famous for hosting RailsClub and developing highload projects.

Slide 3

Slide 3 text

I am a part of gitfm.com gistflow.com So you may know me if you visited Gistflow.com – open source blog platform for developers and GitFM.com – personal recommendation service for Github repos (and it is really smart, there is a big math behind the scene).

Slide 4

Slide 4 text

Refactoring I am quite sure that you have heard about refactoring.

Slide 5

Slide 5 text

Refactoring But now you have one less reason not to do that – recently Ruby version of Refactoring book was published.

Slide 6

Slide 6 text

Martin Fowler, 1999 Meet the founder – Martin Fowler. Endless respect to this guy because he started new programming discipline and I would like to say scientific approach to work with code.

Slide 7

Slide 7 text

The problem In the past refactoring was avoided in development processes. http://en.wikipedia.org/wiki/Code_refactoring#History So the problem I want to discuss today is that refactoring is already the formed technique.

Slide 8

Slide 8 text

Problem Nowadays refactoring is still not used widely. Me But for couple of years of development I have heard only once that someone used this approach to factoring their code.

Slide 9

Slide 9 text

And our projects looks like Bad factored code leads projects to look like this.

Slide 10

Slide 10 text

Instead of Instead of this.

Slide 11

Slide 11 text

Plan • Productivity • Testing • What is refactoring? • Code smells • Let’s refactor! • How to rate our code? • Conclusion The plan.

Slide 12

Slide 12 text

* What is refactoring? Disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior Martin Fowler Just read the definition. We will build the whole philosophy on top of it.

Slide 13

Slide 13 text

*Productivity. Self refactoring. If we decided to make our programs better why not to begin with ourselves?

Slide 14

Slide 14 text

Let’s use aliases! alias s="sublime" alias g="git" alias cpd="cap production deploy" alias csd="cap staging deploy" p() { cd ~/Sites/$1; } _p() { _files -W ~/Sites -/; } compdef _p p Super duper captain tip – use aliases! And not only variables – write functions for example like this – navigating to project in Sites directory.

Slide 15

Slide 15 text

Economy cap production deploy vs cpd 3 sec * 20 a day * 30 days = 30 min/month And it can saves you some time and you can spend this time refactoring!

Slide 16

Slide 16 text

Rails generators gem install zeus zeus init zeus start 9 sec * 20 a day * 30 days = 90 min/month Use zeus to preload your app and not to waste time waiting.

Slide 17

Slide 17 text

Apps from templates rails new myapp -m template.rb https://github.com/evrone/omniauth-github-bootstrap And if you work with Github API often create an app template and start each project from this point.

Slide 18

Slide 18 text

* Testing Remember the definition of refactoring? How do we know that we haven’t changed anything?

Slide 19

Slide 19 text

Refactoring is started with tests. Want to refactor – cover code with tests first.

Slide 20

Slide 20 text

How we test? • Test::Unit • RSpec • Capybara • Cucumber We use a lot of tools to test our apps. But do you usually run `rspec spec` before each commit?

Slide 21

Slide 21 text

Continuous Integration So here is the solution.

Slide 22

Slide 22 text

CIs • Travis CI • CI Joe • Bamboo • Jenkins You may heard about Travis CI but there are a lot off tools more. Though I still think that Travis are the best :)

Slide 23

Slide 23 text

Jenkins statistics We chose Jenkins and here is our stats for about a month – each step is a new feature and each red pile in the bottom stands for amount of broken tests. So as you can see we save our users from 500 pages couple of times and not deployed bad code.

Slide 24

Slide 24 text

Always use separate server for CI. And never never never install Jenkins or any CI on you production server. “Oh captain...” I hear :D

Slide 25

Slide 25 text

And how about a profiler? But how do you know that your code still work fast after all refactoring? You need a profiler and I don’t know anything better than NewRelic.

Slide 26

Slide 26 text

* Refactoring Disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior Martin Fowler Just a reminder.

Slide 27

Slide 27 text

What for? • Complexity • Readability • Maintainability • Extensibility So for ourselves we need to understand why do we need to refactor and also it is useful if we need to explain this to our employer. It is 100% profit.

Slide 28

Slide 28 text

Code Smell Any symptom in the source code of a program that possibly indicates a deeper problem. Kent Beck So in refactoring I noticed only one term and it is Code Smell. You may have heard it a lot :)

Slide 29

Slide 29 text

Repeated code • In different classes • In one class • In one method Let’s start with the most famous code smell – is repeated code and it could be repeated in many ways.

Slide 30

Slide 30 text

Loooong methods def barny_says puts 'legen' ... ... ... ... ... ... ... ... ... ... puts 'wait for it' The second code smell in my list is long method. And methods could be reaaaaly

Slide 31

Slide 31 text

puts 'wait for it' ... ... ... ... ... ... ... ... ... ... puts 'dary' end long.

Slide 32

Slide 32 text

FAAAAT models Another problem is fat model. There could be 300 methods and it is a signal that this only model do much, for example if you see methods with the same prefix it is probably time to move this methods to another class (named with prefix).

Slide 33

Slide 33 text

Too many params Long methods definitions are bad because you need to scroll code horizontally our it brakes the formatting so use objects.

Slide 34

Slide 34 text

OMG def self.reset_counters #resettings counters puts "Clean counters" Count.where(:count_type => "CatalogGlobalRubric").each{ |count| count.destroy } catalogs = Catalog2.all puts "Calculation" size = catalogs.size nom = 0 catalogs.each{|catalog| nom = nom + 1 puts nom.to_s + " from " + size.to_s catalog.counters_inc if catalog.approved } return "That’s it!!!" end And here comes the bullshit – in this method you can see many code smells - ambiguous variables, obvious comments, long method, bad naming, everything.

Slide 35

Slide 35 text

Know your tools! def mydomain? site.domain == 'mydomain' ? true : false end page = (@topic.replies.approved.count / Reply.per_page).to_i page += 1 if ((@topic.replies.approved.count % Reply.per_page).to_i > 0) All code smells before were about understanding the code. I mean that we READ the code and not INTERPRET it as a computer. So bad code make us interpret and it takes a lot of our energy and creativity, this is why we do less and this is why we are getting bored and tired. This is why we should refactor! Here couple of code smells which are about knowing of Ruby standard lib.

Slide 36

Slide 36 text

Seriously, know your tools! @doc = StaticDocs.find_by_link(params[:id]) raise ActiveRecord::RecordNotFound if !@doc Count.where(:count_type => "CatalogGlobalRubric").each{ |count| count.destroy } Also in Rails there is its own specific and when I want to write some method I first look for in Rails API and in 60% of cases I find it.

Slide 37

Slide 37 text

* Let’s refactor! • Extract/inline method • Replace conditional with method • Replace temp variable with method • Extract/inline class • ... The are quite a lot of refactoring techniques and I am quite sure you know some of them. But checkout Martin’s Fowler book to read them all and remember. As I said before this is very well structured list of refactorings.

Slide 38

Slide 38 text

Refactoring != Rehacktoring @kytrinyx And always remember why you refactor.

Slide 39

Slide 39 text

Rename method “In Computer Science there are only two problem – naming and cache invalidation.” Phil Karton My favorite refactoring (and the most difficult for me) is renaming. Your code should be readable besides interpretable.

Slide 40

Slide 40 text

* How to rate our code? So you are 5 minutes from refactoring – you just need a starter point. But since we deal with Ruby why not to use Ruby to analize our code for code smells?

Slide 41

Slide 41 text

ruby_parser Sounds fresh so let’s look at some simple class. How can we analize it? We probably need a better structure - may be array or hash.

Slide 42

Slide 42 text

S-expressions s(:class, :User, nil, s(:scope, s(:block, s(:call, nil, :attr_accessor, s(:arglist, s(:lit, :name))), s (:defn, :initialize, s(:args, :name), s(:scope, s (:block, s(:lasgn, :name, s(:lvar, :name))))), s (:defn, :say, s(:args), s(:scope, s(:block, s (:call, nil, :puts, s(:arglist, s(:str, "hello"))))))))) So ruby_parser gem provides necessary functionality. It converts ruby code into sexp format which could be analized.

Slide 43

Slide 43 text

Instruments • gem ‘reek’ • gem ‘flay’ • gem ‘flog’ • CodeClimate The most well known solutions for analizing are listed here. For me `reek` is the most useful - it shows what should be refactored, where and how. Be sure to check it.

Slide 44

Slide 44 text

Let’s refactor! And let’s refactor!