Should I be avoiding circular imports?

Are circular imports (two files importing from each other) indication of poor design that should be refactored? Why does zig support them?

Zig supports circular dependencies, they’re ok to have.

4 Likes

One downside of circular imports is that you can’t do zig test independently on each file. Making changes is somewhat harder because of that as you have to constantly use --test-filter to suppress tests in the other file (which might fail simply because you haven’t gotten around to adjusting them).

So far as I’ve been able to determine, as soon as you import a package with the build system, zig test goes out the window anyway, because it can’t find that package.

So using the .filters argument to b.addTest is already essential at that point. The filtering happens at compile time, so the excluded tests don’t even get compiled, let alone run. It takes some extra setup but works just as well: zig test src/something.zig is basically the same as zig build test -Dtest-filter="something.", and works with imports.

I’m sure it could be shaved down further with a shell alias or such, but I just use history, and don’t see a slightly longer command as a problem in practice.

1 Like

It works fine when you @import by path.

I think what @mnemnion meant is an external package. I pretty much do the same thing now: instead of zig test, just do the zig build test filter.

1 Like

Yes, that’s the “with the build system” part. @import of files doesn’t require the build system’s involvement, so zig test works fine.

It also wouldn’t surprise me if zig test were integrated with build dependencies at some future point, either. At the moment it isn’t compatible with a file using an import from module.addImport.

I think you can use the command line flags to specify module imports for zig test, I haven’t done it, because I prefer using a build step, but I think it works.

The language allows it, but I personally avoid them if I can.

The only place I have hit circular references causing actual issues is with cImport/cInclude (which apparently are slated to go away at some point).

In general, circular references tend to be harder to reason about (lots of ink has been spilled about that). In addition, they often cause tools like compilers and IDEs to freak out in pathological edge cases.

So, I avoid them, but I also won’t waste a lot of time trying to remove them if they exist.

1 Like