Gedweb
Gedweb

Reputation: 739

More than one file in module

I work on an implementation of the Repository pattern in Rust.

I need to have two (or more) files:

Problem:

One file implies one mod. This means that for a function in repository.rs to have access to struct field from entity.rs it is required that field be pub. Is there some way to avoid this?

Upvotes: 1

Views: 158

Answers (1)

Matthieu M.
Matthieu M.

Reputation: 299730

In Rust, modules are self-contained. Unlike C++ or Java there is no cheating via either friend or the use of reflection.

As such, if you (arbitrarily) attempt to separate the definition of the struct from the methods in charge of maintaining its encapsulation, you will fight against the language.


Solution 1: Prefer non-member non-friend functions

Define the methods absolutely requiring access to the fields in entity.rs; if you follow the "Prefer non-member non-friend functions" guideline from C++, you should see that actually most methods do NOT need to access the fields directly. For example, empty can be defined in terms of len:

fn empty(c: &Container) -> bool { c.len() == 0 }

Then, repository.rs can add many other methods if it needs to, but has to go through the "minimal" interface exported by entity.rs to achieve its needs. Since you are in control of both modules, you can tweak the methods of entity.rs at will anyway so it should not be an issue.

I would point out that encapsulation-wise, this is the sensible decision: reducing the number of methods that may access the internals of an object reduces the number of methods that may put this object in an invalid state.

This solution is advantageous because you are not fighting the language.


Solution 2: Total split

Another solution is to duplicate your entities:

  • have the internal entity, entirely public
  • have the external entity, opaque

This is achieved by:

pub struct SomeEntImpl {
    pub field0: i32,
}

pub struct SomeEnt {
    inner: SomeEntImpl,
}

The authorized modules will be given references to a SomeEntImpl, while others will have to use the restricted interface available through SomeEnt. The control over who sees what will be achieved by careful exports.

This solution will probably drive you insane.

Upvotes: 5

Related Questions