From 8c8818f9b01971ead4bb12a039571914fe532650 Mon Sep 17 00:00:00 2001 From: SevenWaysDP Date: Fri, 26 Apr 2024 11:54:26 +0200 Subject: [PATCH 1/9] add docu for modules and sub modules --- .../Coding-Guidelines/modules-submodules.md | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 docs/schulcloud-server/Coding-Guidelines/modules-submodules.md diff --git a/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md new file mode 100644 index 0000000..5cf06b7 --- /dev/null +++ b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md @@ -0,0 +1,66 @@ +# Implementation and usage of modules, submodule and barrel files in our project + +In this guide, we'll cover how to use modules, submodules and barrel files in our project. These concepts help you organize your code into separate files and directories, making it easier to manage and maintain. + +## Modules and Submodules + +In our project, modules are a way to create separate scopes. This means that interfaces, use cases, services, etc., declared in a module are not visible outside the module unless they are explicitly exported using the `export` keyword. To import a module, you use the `import` keyword followed by the module name. Here's an example: + +```typescript +import { ModuleName } from '@modules/module-name'; +``` + +Submodules are modules that are part of a larger module. They should be used within the main module. If it is necessary to use parts of the submodule outside the main module, the main module should export this via its barrel file(index.ts): + + +```typescript +// @modules/module-name/index.ts +export { SubmoduleServiceName } from './submodule-name/service.ts'; +``` + +## Barrel Files + +Barrel files are a way to rollup exports from several modules into a single convenient module. The barrel itself is a module file that re-exports selected exports of other modules. + +If you have several related modules in a directory, you can create a barrel to re-export all of their exports. This allows other modules to import everything from the barrel instead of having to import things individually from each module. + +Here's an example of a barrel file: + +```typescript +// @modules/module-name/index.ts +export { PublicService } from './services/public-service.ts'; +export * from './interfaces'; +export * from './submodule-name/interfaces'; +``` + +And here's how you can import from the barrel: + +```typescript +// @modules/other-module-name/service.ts +import { PublicService, InterfaceOfModule, InterfaceOfSubmodule } from '@modules/module-name'; +``` + +## Handling Circular Dependencies + +Circular dependencies occur when Module A depends on Module B, and Module B also depends on Module A. This can lead to unexpected behavior and hard-to-diagnose bugs. + +Here are some strategies to handle circular dependencies: + +1. **Refactor Your Code**: The best way to handle circular dependencies is to refactor your code to remove them. This might involve moving some code to a new module to break the dependency cycle. + +```typescript +// @modules/moduleC/service.ts +import { PublicService, InterfaceOfModule, InterfaceOfSubmodule } from '@modules/moduleA'; +import { PublicService, InterfaceOfModule, InterfaceOfSubmodule } from '@modules/moduleB'; +``` + +2. **Use Interfaces**: If the circular dependency is due to types, you can use interfaces and type-only imports to break the cycle. + +```typescript +// @modules/moduleC/service.ts +import { type PublicService } from '@modules/moduleA'; +import { type PublicService } from '@modules/moduleB'; +``` + +Remember, circular dependencies are usually a sign of tightly coupled code and can lead to maintenance issues down the line. It's best to refactor your code to avoid them if possible. + From 1974f48629b5172bf18e7c6b9b07dd99088d8b36 Mon Sep 17 00:00:00 2001 From: Cedric Evers <12080057+CeEv@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:45:19 +0200 Subject: [PATCH 2/9] Add svg for modules and submodules --- .../img/Modules-SubModules.svg | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/schulcloud-server/img/Modules-SubModules.svg diff --git a/docs/schulcloud-server/img/Modules-SubModules.svg b/docs/schulcloud-server/img/Modules-SubModules.svg new file mode 100644 index 0000000..c07e949 --- /dev/null +++ b/docs/schulcloud-server/img/Modules-SubModules.svg @@ -0,0 +1,21 @@ + + + + + + + + RepoDomainApiModuleRepoDomainApimodule.tsapi-module.tsconfig.tsindex.ts (explicit useable "interface". Also for other submodules,inside the module it self)Sub-ModuleRepoDomainApimodule.tsapi-module.tsconfig.tsindex.ts (explicit)Sub -ModuleRepoDomainApiSub-ModuleRepoDomainApiSub -Modulemodule.tsapi-module.tsconfig.tsindex.ts (define explicit what can be used from outside when someone import this module)Modulemodule.tsapi-module.tsconfig.tsindex.ts (define explicit what can be used from outside when someone import this module)module.tsapi-module.tsconfig.tsindex.ts (explicit)module.tsapi-module.tsconfig.tsindex.ts (explicit) \ No newline at end of file From 033733fdbf01a90420d32502e4cf00e9cd36195e Mon Sep 17 00:00:00 2001 From: Cedric Evers <12080057+CeEv@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:49:08 +0200 Subject: [PATCH 3/9] replace svg with one that has background --- .../img/Modules-SubModules.svg | 21 ------------------- .../img/Modules-SubModules_background.svg | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 docs/schulcloud-server/img/Modules-SubModules.svg create mode 100644 docs/schulcloud-server/img/Modules-SubModules_background.svg diff --git a/docs/schulcloud-server/img/Modules-SubModules.svg b/docs/schulcloud-server/img/Modules-SubModules.svg deleted file mode 100644 index c07e949..0000000 --- a/docs/schulcloud-server/img/Modules-SubModules.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - RepoDomainApiModuleRepoDomainApimodule.tsapi-module.tsconfig.tsindex.ts (explicit useable "interface". Also for other submodules,inside the module it self)Sub-ModuleRepoDomainApimodule.tsapi-module.tsconfig.tsindex.ts (explicit)Sub -ModuleRepoDomainApiSub-ModuleRepoDomainApiSub -Modulemodule.tsapi-module.tsconfig.tsindex.ts (define explicit what can be used from outside when someone import this module)Modulemodule.tsapi-module.tsconfig.tsindex.ts (define explicit what can be used from outside when someone import this module)module.tsapi-module.tsconfig.tsindex.ts (explicit)module.tsapi-module.tsconfig.tsindex.ts (explicit) \ No newline at end of file diff --git a/docs/schulcloud-server/img/Modules-SubModules_background.svg b/docs/schulcloud-server/img/Modules-SubModules_background.svg new file mode 100644 index 0000000..d0f6588 --- /dev/null +++ b/docs/schulcloud-server/img/Modules-SubModules_background.svg @@ -0,0 +1,21 @@ + + + + + + + + RepoDomainApiModuleRepoDomainApimodule.tsapi-module.tsconfig.tsindex.ts (explicit useable "interface". Also for other submodules,inside the module it self)Sub-ModuleRepoDomainApimodule.tsapi-module.tsconfig.tsindex.ts (explicit)Sub -ModuleRepoDomainApiSub-ModuleRepoDomainApiSub -Modulemodule.tsapi-module.tsconfig.tsindex.ts (define explicit what can be used from outside when someone import this module)Modulemodule.tsapi-module.tsconfig.tsindex.ts (define explicit what can be used from outside when someone import this module)module.tsapi-module.tsconfig.tsindex.ts (explicit)module.tsapi-module.tsconfig.tsindex.ts (explicit) \ No newline at end of file From 0190bf2fb8244d792cba0181c5a58ab43aaab83d Mon Sep 17 00:00:00 2001 From: Cedric Evers <12080057+CeEv@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:03:04 +0200 Subject: [PATCH 4/9] add svg to show allowed server area dependencies --- .../img/server_area_dependency.svg | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/schulcloud-server/img/server_area_dependency.svg diff --git a/docs/schulcloud-server/img/server_area_dependency.svg b/docs/schulcloud-server/img/server_area_dependency.svg new file mode 100644 index 0000000..fcc998a --- /dev/null +++ b/docs/schulcloud-server/img/server_area_dependency.svg @@ -0,0 +1,21 @@ + + + + + + + + @shared@infra@core@modulessubmodules@apps@infra@modulessubmodules \ No newline at end of file From b638f22dc22607f5671df8f6e5718f8547147a4f Mon Sep 17 00:00:00 2001 From: Cedric Evers <12080057+CeEv@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:00:40 +0200 Subject: [PATCH 5/9] Invert dependency file for sub modules in svg --- .../{server_area_dependency.svg => server_area_dependency_v1.svg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/schulcloud-server/img/{server_area_dependency.svg => server_area_dependency_v1.svg} (100%) diff --git a/docs/schulcloud-server/img/server_area_dependency.svg b/docs/schulcloud-server/img/server_area_dependency_v1.svg similarity index 100% rename from docs/schulcloud-server/img/server_area_dependency.svg rename to docs/schulcloud-server/img/server_area_dependency_v1.svg From f48822303480ba68bcfdea187a2426004ad74881 Mon Sep 17 00:00:00 2001 From: Cedric Evers <12080057+CeEv@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:04:30 +0200 Subject: [PATCH 6/9] update image --- ...ver_area_dependency_v1.svg => server_area_dependency_v2.svg} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename docs/schulcloud-server/img/{server_area_dependency_v1.svg => server_area_dependency_v2.svg} (87%) diff --git a/docs/schulcloud-server/img/server_area_dependency_v1.svg b/docs/schulcloud-server/img/server_area_dependency_v2.svg similarity index 87% rename from docs/schulcloud-server/img/server_area_dependency_v1.svg rename to docs/schulcloud-server/img/server_area_dependency_v2.svg index fcc998a..e573b71 100644 --- a/docs/schulcloud-server/img/server_area_dependency_v1.svg +++ b/docs/schulcloud-server/img/server_area_dependency_v2.svg @@ -18,4 +18,4 @@ - @shared@infra@core@modulessubmodules@apps@infra@modulessubmodules \ No newline at end of file + @shared@infra@core@modulessubmodules@apps@infra@modulessubmodules \ No newline at end of file From 005854a4fd76df8394bf38130b8a0c85db8f4abe Mon Sep 17 00:00:00 2001 From: SevenWaysDP Date: Mon, 6 May 2024 15:22:02 +0200 Subject: [PATCH 7/9] add images --- .../Coding-Guidelines/modules-submodules.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md index 5cf06b7..1f17978 100644 --- a/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md +++ b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md @@ -2,6 +2,8 @@ In this guide, we'll cover how to use modules, submodules and barrel files in our project. These concepts help you organize your code into separate files and directories, making it easier to manage and maintain. +![Module Structure](./../img/Modules-SubModules_background.svg) + ## Modules and Submodules In our project, modules are a way to create separate scopes. This means that interfaces, use cases, services, etc., declared in a module are not visible outside the module unless they are explicitly exported using the `export` keyword. To import a module, you use the `import` keyword followed by the module name. Here's an example: @@ -12,7 +14,6 @@ import { ModuleName } from '@modules/module-name'; Submodules are modules that are part of a larger module. They should be used within the main module. If it is necessary to use parts of the submodule outside the main module, the main module should export this via its barrel file(index.ts): - ```typescript // @modules/module-name/index.ts export { SubmoduleServiceName } from './submodule-name/service.ts'; @@ -29,10 +30,12 @@ Here's an example of a barrel file: ```typescript // @modules/module-name/index.ts export { PublicService } from './services/public-service.ts'; -export * from './interfaces'; -export * from './submodule-name/interfaces'; +export { ServiceInterfaceA, InterfaceB } from './interfaces'; +export { InterfaceC } from './submodule-name/interfaces'; ``` +!!! Please don't export everything from a module in the barrel file. Only export the public API of the module. This will make it easier to understand what the module provides and avoid unnecessary dependencies. And don't use wildcard exports like `export * from './services'` in the barrel file. + And here's how you can import from the barrel: ```typescript @@ -44,6 +47,8 @@ import { PublicService, InterfaceOfModule, InterfaceOfSubmodule } from '@modules Circular dependencies occur when Module A depends on Module B, and Module B also depends on Module A. This can lead to unexpected behavior and hard-to-diagnose bugs. +![Module Structure](./../img/server_area_dependency_v2.svg) + Here are some strategies to handle circular dependencies: 1. **Refactor Your Code**: The best way to handle circular dependencies is to refactor your code to remove them. This might involve moving some code to a new module to break the dependency cycle. @@ -63,4 +68,3 @@ import { type PublicService } from '@modules/moduleB'; ``` Remember, circular dependencies are usually a sign of tightly coupled code and can lead to maintenance issues down the line. It's best to refactor your code to avoid them if possible. - From effb53e71087ecde42bf795f72538aaa724fece7 Mon Sep 17 00:00:00 2001 From: SevenWaysDP Date: Thu, 16 May 2024 15:17:49 +0200 Subject: [PATCH 8/9] code review --- .../Coding-Guidelines/modules-submodules.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md index 1f17978..5c1cab8 100644 --- a/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md +++ b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md @@ -67,4 +67,10 @@ import { type PublicService } from '@modules/moduleA'; import { type PublicService } from '@modules/moduleB'; ``` +3. **Use Events**: If you have a circular dependency between two modules that need to communicate with each other, consider using events to decouple them. This way, one module can emit an event that the other module listens to, without directly importing it. + +- + +- + Remember, circular dependencies are usually a sign of tightly coupled code and can lead to maintenance issues down the line. It's best to refactor your code to avoid them if possible. From 37aa4410b3b3ab3845cb277908a4500c2f95719f Mon Sep 17 00:00:00 2001 From: SevenWaysDP Date: Fri, 17 May 2024 08:20:15 +0200 Subject: [PATCH 9/9] code review --- .../schulcloud-server/Coding-Guidelines/modules-submodules.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md index 5c1cab8..e0a315c 100644 --- a/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md +++ b/docs/schulcloud-server/Coding-Guidelines/modules-submodules.md @@ -21,9 +21,9 @@ export { SubmoduleServiceName } from './submodule-name/service.ts'; ## Barrel Files -Barrel files are a way to rollup exports from several modules into a single convenient module. The barrel itself is a module file that re-exports selected exports of other modules. +Barrel files are a way to rollup exports from several folders into a single convenient nest-module. The barrel itself is a module file that re-exports selected exports of other submodules. -If you have several related modules in a directory, you can create a barrel to re-export all of their exports. This allows other modules to import everything from the barrel instead of having to import things individually from each module. +If you have several related service/interface files in a directory/module that should be publicly accessible, you can create a barrel file to export all these files from the main module again. Here's an example of a barrel file: