Swift: Conceal the Implement content using Internal Properties

Tram Ho

In Swift we have five types of access-level modifier : open , public , internal , fileprivate and private . An internal declared property means that it can only be used within the module for which it is declared. In Swift, by default, all properties are internal, but things will get interesting when we split the code into multiple modules.

In the framework of this article we will see how to access data structures inside the framework classes, while still keeping the internal properties hidden.

Problem

Most current applications store data locally, we have a lot of options such as: Core Data, Realm, SQLite, … And no matter which way you choose it, when the project grows bigger. above 10k, 50k, 100k lines of code then surely we will have to start thinking of dividing them into modules.

Suppose we have a module divided from the main target of the project that contains the code related to manipulating the database. Let’s call it PersistenceKit – following Apple’s naming convention. We can implement this module as a dynamic framework or static framework our choice.

Let’s assume that PersistenceKit will contain many repositories , such as: ArticleRepository, UserRepository, etc. that we will use to fetch and store data. A repository can be implemented as follows:

In the implementation of Repository above, to be able to manipulate the database, we need to use some objects related to the database used in the project, such as:

In order to try to become good and thoughtful programmers, we should:

  • Avoid using singleton or global variables to reference the above objects.
  • Do not allow the users of the PersistenceKit module to know how it implements, ie no one knows that we are using NSManagedObjectContext or DatabasePool or whatever.

Solution

I recently thought about these two things and tried to find a solution that would satisfy me. It is based on a combination of public and internal modifiers. Suppose we declare a struct:

This way the Connection property is accessible from outside PersistenceKit , and the pool property is not. It is not even possible to initialize this struct outside PersistenceKit because the memberwise initializer in this case is internal .

And because the PersistenceKit module users won’t be able to initiate the Connection , we need to give them an instance, like this:

The next thing is to pass the instance of the above Connection to ArticleRepository , as follows:

Thus, from now on we can set up PersistenceKit as follows:

And whenever we want to fetch data, we just need to pass the connection into the ArticleRepository method:

By the way, the framework user will not be able to call Connection.pool directly, because it is not accessible outside PersistenceKit . This way we can ensure that others cannot access the components within PersistenceKit , thereby ensuring cleaner overall architecture .

Summary

The public types that come with internal properties are a very powerful tool, while our framework can still allow users to get what they want, but make sure they don’t know what we’re doing. inside the framework.

Are you using any other approach with public types and internal properties, please let me know by commenting below the article!

Share the news now

Source : Viblo