Review my code please!

Hello everyone!
Is there a kind soul here who can give me some pointers/feedback?
I’ve been doing the Odin project and hackerrank ruby exercises but I am not sure if my code looks good or if I’m doing something terribly wrong. Here is the link to the tic tac toe project. If you have the time, any help is really appreciated!

tic tac toe

I took a look at your code, and it’s alright!

I don’t think there’s such thing as good looking code. If your code is reliable and fast (and sometimes, secure) you don’t need to worry about making it look good and slow. Most programmers can read your code unless it’s brainfuck. If you are writing a code for teaching, for beginners, or you have done something counter intuitive, just make sure to comment. But in this tic-tac-toe, you don’t have to worry about that.

Happy ruby-ing…

1 Like

What do you think about the way I used the observable module? I wanted to register lots of methods in the “action” on_move to invoke them after each turn. But I don’t know if what I did is a good pattern or just good in general.
Also is it ok to put lambdas in modules? In my helper_funcs file I have lots of lambdas but again I am not sure about that.
Thanks for helping!

If you are confused about your code’s good practices, I will suggest you Rubocop gem. It’s very simple.

But I will suggest you not to stress out with a lot of those stupid conventions as long as your code runs perfectly fine and you are not using deprecated things.

Anyway, you can register a lot of methods in a file until you can read it. A file that has 10K lines of code gets a little bit unreadable, so you may want to define the module in multiple file with different methods. You may want to document that at the top.

And to your second question, yes, you can put lambdas inside a module, there’s no warning or error from Ruby, so it’s completely fine:

module X
	D = lambda { |n| n ** 5 }
	
	def self.x(n) 
		D === n
	end
end

p X::D === 5
p X.x(5)

In the above case X::D.call() is a little bit faster than X.x() (when you are doing multiple million calls) because you are avoiding one function call which does the same thing.

Don’t worry much about convention, it will confuse you a lot, and your ruby development journey will be very stressful. When you are working with a team, imagine, a file with mixed 2 space and 1 tab indentation put by different devs. You don’t want that and you need Rubucop or other alternatives so that other developer follow the convention. But here you are writing your own code, and I will suggest not to stress out much and do whatever you like unless that’s uneasy to grasp by others.

1 Like

I am using rubocop, it is amazing! It gave me the idea to register methods because it told me I could do this:

# register event ← method names. Those methods will be called on observable change
player.on_move = %i[switch_player place_move draw_board]

So I am guessing it is a common enough practice. I am just worried I am carrying stuff from c# that in ruby is used in another way.
Thanks for the feedback!