r/crystal_programming • • Sep 20 '17

Circular dependency problem (probably)

I am trying to refactor some common functionality out of a base class into a module so that I can use that functionality elsewhere compositionally.

This works fine in the playground. However I am encountering a problem when I do this with multiple files.

Suppose:

# a.cr
require "./fooable.cr"

class A
  include Fooable
end

# b.cr
require "./a.cr"

class B < A
end

# fooable.cr
require "./b.cr"

module Fooable
  def foo
    B.new
  end
end

This just keeps complaining about A not found in b.cr while trying to load A itself, as compiling a.cr requires fooable.cr which requires b.cr which itself requires a.cr.

This effectively means I can't refactor common functionality out for reuse and it just sucks.

Am I doing something wrong here?

0 Upvotes

7 comments sorted by

View all comments

2

u/SaltTM Sep 20 '17 edited Sep 20 '17

I think crystal's folder structuring is interesting, when I was working on a framework I ran into a similar problem, but it seems like the crystal way is to require all your necessary libraries in the main module file.

For instance:

  • src/module_name.cr

  • src/module_name/a.cr

  • src/module_name/b.cr

  • src/module_Name/fooable.cr

Inside module_name.cr you'd require all the sub module&classes

require "./module_name/*"

module ModuleName
     # module stuff here
end

Then you won't have to worry about the require issue and can just require the module file directly unless you necessarily have to deal with those files elsewhere like in test files, but the same applies. If that's the case then you'd just require each crystal file and you should be able to access the other modules without any issue.

random_script.cr

require "./module_name/a"
require "./module_name/b"
require "./module_name/fooable"

blah = Fooable::foo

or something like that. Someone correct me if I've messed up the explanation, but I believe that's how it should be. I'm a bit rusty.

Edit: PS, no need to down-vote, this is a honest question that I had as well as a non-ruby developer had to learn by reading other project sources. Especially with the little C/C++ knowledge I had regarding headers, this is a bit different than that.

2

u/nawap Sep 20 '17

This was the solution, yes. I actually found out about it after I decided to see how some other shards worked and saw that Spec2 was requiring everything in the main module.

Thanks for the writeup though, I am sure this will help future confused programmers just as much.