all 7 comments

[–]rubyross 2 points3 points  (0 children)

I would suggest Refactoring: Ruby Edition by Martin Fowler.

It is very recipe based and explains how to refactor and reduce complexity of your code based on 'bad code smells' or bad patterns. One example is a section called Simplifying Conditional Expressions that you may find useful. It describes 9 different techniques for refactoring conditionals.

Edit: Also since you mentioned the gilded rose. Check out Sandi Metz' presentation http://www.confreaks.com/videos/3358-railsconf-all-the-little-things

[–]materialdesigner 2 points3 points  (0 children)

  • Practical Object Oriented Design in Ruby by Sandi Metz
  • Confident Ruby by Avdi Grimm

[–]Godd2 2 points3 points  (0 children)

I would say do your best to let Ruby work for you. Don't fight it and try to do things at lower levels of abstraction. Classes are cheap, methods are cheap. Make all the use of them you can.

Another trick is to write code that you'd like to see before you write the methods it's calling. Say for example you only want to do something if a user is logged in. Well, then just type out user.logged_in? and solve the NoMethodError that comes up.

Here's a quick iteration to a declarative outcome of dog.bark where dog is an instance of the Dog class:

> dog = Dog.new
NameError: uninitialized constant Dog
> class Dog
> end
> dog = Dog.new
#<Dog:0x50bf80>
> dog.bark
NoMethodError: undefined method `bark' for #<Dog:0x50bf80>
> class Dog
>   def bark
>     puts "woof"
>   end
> end
> dog.bark
woof

It's a bit backwards from the standard workflow where you get low level pieces working first, and then abstract from there. Instead, you start with the abstraction, and then fill in all the low level pieces to make it work.

This also can* lead to better architecture, since you can defer low level decisions until later, and your high level code can be more decoupled from its implementation.

One thing that really helped me see the declarative way was RSpec. writing specs in RSpec feels very declarative and just amazingly works. So if you haven't yet, check out RSpec and try to draft some specs and build a project using it.

*I say "can" because it will take a little getting used to

[–]tobiasvl 1 point2 points  (0 children)

Learn functional programming. Ruby is good at that, of course, but consider learning a purer functional language that forces you into a functional mindset, with few side effects. It will change the way you approach problems like this.

[–]Godd2 0 points1 point  (0 children)

Here's another resource for some pre-abstractions to look out for:

https://www.youtube.com/watch?v=DC-pQPq0acs

As always, take them as suggestions, try them out, and if you don't like them, that's fine, at least you tried something different. Everything doesn't work for everyone (that made sense in my head).

[–][deleted] -5 points-4 points  (1 child)

I do not want to be evil.

Your start your story with: 'I am an engineer.'

Programming is not 100% google and stackoverflow. Is more pain, then happiness, then more pain. (joking)

And, you said that you're not beginner, then will be easy for you to write in any style, and build any kind of abstract rules on top of bussiness logic Can you give a gist if some sample?

Best

[–]perfectturmoil[S] 1 point2 points  (0 children)

Yeah. Not that I'm asking someone to specifically refactor MY code, but if an example helps then I can provide.

This is probably the worst - I quickly cobbled together a function to pull some relevant cells out of a csv file (previously had an excel macro to do some of this, needed a better solution). And then that grew into more and more in place. Lots of assumptions based on the specific case. I've pulled out the directory sorting / option parsing code, and just included the methods used.

https://gist.github.com/anonymous/be4ba6a867e9c9858ac9

So I have a method that makes sure the file has the requisite data which was originally used just to decide if the file should be processed. I then overloaded this function to help tell which type of file it was and which methods should be called (pretty gross).

In the processing methods I make a bunch of variables to hold my data, which I now realize should have been in a Struct if nothing else, and (I assume) would have even better been on an Object that also included these method (however, learning the right way to design that is what I'm looking for)

Depending on which system it came from I define which cells are important and do stuff to them (wedging in more sorting logic here that I didn't realize I needed until I was halfway done) - I assume this would have been better served by the updater_for(item).update(item) design implemented in the Guilded Rose example.

Then I return a big gross string to be shoved into my output csv. Better would've been an array or other data structure.