Modular Encapsulation in Large-Scale GraphQL Projects
Tags: graphql, graphqlmodules
Published: 2021-07-29 09:56:23

> This article was published on Monday, January 7, 2019 by [Arda Tanrikulu](https://twitter.com/ardatanrikulu) @ [The Guild Blog](https://the-guild.dev/)

**TL;DR**: If you are writing a large-scale project, it's necessary to understand the relations
between your pieces of code, and how they effect each other. Otherwise, it might be difficult to
deal with changes later.

While developing a **large-scale project**, removing, changing and modifying parts of the project
can become a very time-consuming and risky task, because understanding the full side-effects of
those changes is very hard.

In [GraphQL-Modules](https://graphql-modules.com), you can declare your modules in a feature-based
structure, with clear enforced boundaries and avoid unexpected side-effects during development.

Each module can declare its own scope of the complete schema:

!\[]\(/medium/c806f0ae70dca7a4d1e434736f241ed5.png 'Every module has its own schema, context and DI
container. Here you can see AuthModule is appended to UserModule. But, other modules don't import
AuthModule. So, they cannot access directly AuthModule DI container or context.')

Each module has its own ***schema***, ***context***, ***typeDefs***, ***resolvers,*** and
business-logic and each module is encapsulated, which limits the module's access to only its own
parts of the schema.

**So, what's the real benefit of this?**

Let's assume you have an authentication module;

After a while, you decided to use ***AccountsJS*** in your ***GraphQL*** project which has
completely different implementation than the existing one.

This can be a risky change, because you're afraid of breaking a lot of things, and you can't be sure
about the all the places in your code that uses values affected by the authentication module, for
example the global context.

With GraphQL-Modules' approach of encapsulation, even the context is completely encapsulated, so
every module that uses your existing ***AuthenticationModule***'s ***context*** in defined on the
`imports` of the dependent modules, and its interface is already extended by
***AuthenticationModule***'s ***context*** if you're using *TypeScript*. When it is removed, you
will notice that change on compile-time immediately.

Let's take a look at some code, to show how GraphQL Modules makes you create those dependencies
explicitly.

`AppModule` is our top Application Module;

```typescript
import { GraphQLModule } from '@graphql-modules/core'
import { AuthenticationModule } from './modules/auth.module'

const AppModule = new GraphQLModule({
  imports: [
    AuthenticationModule, //this module has `user` in its context
    SomeImportantModuleThatUsesAuthenticatedContext
    // ...
  ]
})
```

And there is another module that tries to use `AuthenticationModule`'s context, but it doesn't
import `AuthenticationModule`. In this case, it is not possible to get anything from
`AuthenticationModule` in the resolvers, because it is not imported. The following module doesn't
know anything about `AuthenticationModule`.

```ts
const SomeImportantModuleThatUsesAuthenticatedContext = new GraphQLModule({
  typeDefs: SOME_TYPE_DEFS_HERE,
  imports: [
    // ...
    // This module doesn't import AuthenticationModule
    // ...
  ],
  resolvers: {
    // ...
    Query: {
      getUser(root, args, context) {
        return context.user // Oops! Undefined!
      }
    }
    // ...
  }
})
```

To fix this, we need to import `AuthenticationModule` into that 'important' module to make it able
to access `AuthenticationModule`'s context like below;

```ts
const SomeImportantModuleThatUsesAuthenticatedContext = new GraphQLModule({
  typeDefs: SOME_TYPE_DEFS_HERE,
  imports: [
    // ...
    // This module imports AuthenticationModule
    AuthenticationModule
    // ...
  ],
  resolvers: {
    // ...
    Query: {
      getUser(root, args, context) {
        return context.user // Yes, we have that user HERE!
      }
    }
    // ...
  }
})
```

So, these examples above show us that the encapsulation can be very important in the long term of
our project development.

**We think modular approach is not just merging schemas and concatenate context factory functions to
each other.**

Having a tool that knows how to **encapsulate modules** and **force this policy**, makes it much
easier to write modular schema, and later, even reuse existing modules and share them across
multiple projects.

# All Posts about GraphQL Modules

*   [GraphQL Modules — Feature based GraphQL Modules at scale](/blog/graphql-modules)
*   [Why is True Modular Encapsulation So Important in Large-Scale GraphQL Projects?](/blog/modular-encapsulation-graphql-modules)
*   [Why did we implement our own Dependency Injection library for GraphQL-Modules?](/blog/dependency-injection-library-in-graphql-modules)
*   [Scoped Providers in GraphQL-Modules Dependency Injection](/blog/graphql-modules-scoped-providers)
*   [Writing a GraphQL TypeScript project w/ GraphQL-Modules and GraphQL-Code-Generator](/blog/graphql-typescript-modules-codegen)
*   [Authentication and Authorization in GraphQL (and how GraphQL-Modules can help)](/blog/graphql-modules-auth)
*   [Authentication with AccountsJS & GraphQL Modules](/blog/accountsjs-graphql-modules)
*   [Manage Circular Imports Hell with GraphQL-Modules](/blog/manage-circular-imports-hell-in-graphql-modules)