Free AI web copilot to create summaries, insights and extended knowledge, download it at here
4376
Abstract
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> paymentService: PaymentService, <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> moderationService: ModerationService </span>) {}
<span class="hljs-keyword">public</span> <span class="hljs-title function_">createPost</span>(<span class="hljs-attr">args</span>: <span class="hljs-title class_">CreatePostArgs</span>): <span class="hljs-title class_">Post</span> { <span class="hljs-keyword">const</span> post = <span class="hljs-variable language_">this</span>.<span class="hljs-property">postRepository</span>.<span class="hljs-title function_">create</span>(args);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">reputationService</span>.<span class="hljs-title function_">increaseReputation</span>(args.<span class="hljs-property">userId</span>);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">notificationService</span>.<span class="hljs-title function_">notifyFollowersAboutPost</span>(post);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">userService</span>.<span class="hljs-title function_">updateUserActivity</span>(<span class="hljs-string">'post.created'</span>, post);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">trackingService</span>.<span class="hljs-title function_">registerTrackable</span>(<span class="hljs-string">'post'</span>, post);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">moderationService</span>.<span class="hljs-title function_">checkPostContentForViolations</span>(post.<span class="hljs-property">content</span>);
<span class="hljs-keyword">if</span> (args.<span class="hljs-property">isPremium</span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-property">paymentService</span>.<span class="hljs-title function_">chargeUserForPremiumPost</span>(args.<span class="hljs-property">userId</span>);
}
<span class="hljs-keyword">return</span> post;
} }</pre></div><p id="154d">This example is obviously made up, so please don’t pay too much attention to the details. I just want you to notice how many services <code>PostService</code> is dependent on and imagine that these services may also be dependent on PostService. For example, the notification service may require additional data from the post service to dispatch notifications, or the <code>ModerationService</code> may need to modify the post again via <code>PostService</code> after moderation. This is where circular dependencies occur.</p><p id="96c0">So now that we have a grasp of the problem, let’s explore the solution that I want to propose.</p><h1 id="c471">The solution</h1><p id="72f0">The solution I want to propose for this problem is to use the well-known concept of Event-Driven Architecture. Instead of calling all subsequent actions from the <code>createPost</code> method, we will simply create the post there and emit an event. Then, any module interested in performing some action related to the event may do so without crossing its logical borders.</p><p id="53d2">NestJS already comes with handy tools that we can use to benefit from events. If you don't yet have the package installed, you can simply add <code>@nestjs/event-emitter</code> to your application.</p><div id="9629"><pre>yarn <span class="hljs-keyword">add</span> @nestjs/<span class="hljs-keyword">event</span>-emitter</pre></div><p id="32cf">And when the package is installed, add the <code>EventEmitterModule</code> to the root module of your application.</p><div id="e0ec"><pre><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>; <span class="hljs-keyword">import</span> { EventEmitterModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/event-emitter'</span>;
<span class="hljs-meta">@Module(<span class="hljs-params">{ imports: [ EventEmitterModule.forRoot(<span class="hljs-params"></span>), // ... ], }</span>)</span> export <span class="hljs-keyword">class</span> <span class="hljs-title class_">AppModule</span> {}</pre></div><p id="f073">When we have it ready, we may simply ge
Options
t rid of all <code>PostService</code> dependencies and replace them with only one — <code>EventEmitter2</code>. After this, we may also remove subsequent method invocations from the <code>createPost</code> method and instead emit an event with its key and payload. The payload may be defined as a separate interface or class if you wish, but here, for presentation purposes, I will just emit the created post as a payload.</p><div id="86c2"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">PostsService</span> { <span class="hljs-title function_">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> eventEmitter: EventEmitter2</span>) {}
<span class="hljs-keyword">public</span> <span class="hljs-title function_">createPost</span>(<span class="hljs-attr">args</span>: <span class="hljs-title class_">CreatePostArgs</span>): <span class="hljs-title class_">Post</span> { <span class="hljs-keyword">const</span> post = <span class="hljs-variable language_">this</span>.<span class="hljs-property">db</span>.<span class="hljs-property">posts</span>.<span class="hljs-title function_">create</span>({ ... }); <span class="hljs-variable language_">this</span>.<span class="hljs-property">eventEmitter</span>.<span class="hljs-title function_">emit</span>(<span class="hljs-string">'post.created'</span>, post);
<span class="hljs-keyword">return</span> post;
} }</pre></div><p id="a801">The last thing we have to do is to add a listener to the modules that may be interested in this event. For example, in the notification module, we may have a listener as below. In the other modules, the code will be pretty much the same, just other services will be involved in event handling.</p><div id="c0ad"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">NotificationsListener</span> { <span class="hljs-title function_">constructor</span>(<span class="hljs-params"> <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> notificationsService: NotificationsService </span>) {}
<span class="hljs-meta">@OnEvent</span>(<span class="hljs-string">'post.created'</span>) <span class="hljs-title function_">handlePostCreated</span>(<span class="hljs-params">post: Post</span>) { <span class="hljs-variable language_">this</span>.<span class="hljs-property">reputationService</span>.<span class="hljs-title function_">notifyFollowersAboutPost</span>(post); } }</pre></div><p id="9b3f">This way, the <code>NotificationService</code> and <code>PostService</code> are only loosely coupled now. The <code>PostService</code> is no longer dependent on <code>NotificationService</code>. We get rid of circular dependency here, yet we keep the functionality still working — Yay!</p><h1 id="ea7f">Summary</h1><p id="bf46">To sum up, in this article we explored the proposition of introducing events into your application to solve the issue of circular dependencies. This approach helps modules to stay within their borders yet react to actions performed in another module as well. Even though this way may not be applicable to all solutions it definitely may fix the one presented today.</p><p id="c9dc">I want to say thank you to all who read this article. I would love to hear your thoughts about this proposal and your ways of tackling circular dependencies in your applications, so feel free to share.</p><p id="913c">Don’t forget to check out my other articles for more tips and insights. Happy hacking!</p><h1 id="7cf6">Stackademic 🎓</h1><p id="d5c3">Thank you for reading until the end. Before you go:</p><ul><li>Please consider <b>clapping</b> and <b>following</b> the writer! 👏</li><li>Follow us <a href="https://twitter.com/stackademichq"><b>X</b></a><b> | <a href="https://www.linkedin.com/company/stackademic">LinkedIn</a> | <a href="https://www.youtube.com/c/stackademic">YouTube</a> | <a href="https://discord.gg/in-plain-english-709094664682340443">Discord</a></b></li><li>Visit our other platforms: <a href="https://plainenglish.io"><b>In Plain English</b></a><b> | <a href="https://cofeed.app/">CoFeed</a> | <a href="https://venturemagazine.net/">Venture</a> | <a href="https://blog.cubed.run">Cubed</a></b></li><li>More content at <a href="https://stackademic.com"><b>Stackademic.com</b></a></li></ul></article></body>
Dear Reader- The music video above was what I was listening to while writing this story. I added it to better place you within a whole scene to enhance your reading experience.
My village lays ‘wake, restless upon the Moon’s absence. The Night is merciless, the unyielding executioner. Shielding its bloodlust in a funeral shroud as it beckons the ole’ hovering shadow. Bellowing across the hills, I hear the sound of War Drums keeping rhythm to a thousand mothers breakin’ hearts. Marching in time with Death’s ghastly stride. I can’t spare to bury another. I will join my’ courageous sons and lovin’ husband in eternal slumber. If my gut holds the truth and I must place my last livin’ son on the funeral pyre, my body will ash ‘long side him. I no longer wish to suffer another moment in anguish….
My family be my heart and soul.
“Oh, my love please lead our son and Scotland to victory.” “Bring him back to me, may I not outlive our youngest boy”
“Alba gu bràth”
-Anna V-
(“ Alba gu bràth” -Sottish Gaelic to English- “Long live Scotland”.) For more about Scotland’s fight for Independence, I left this article below for you to read if you wish :)
-Author Notes- I started writing while listening to a YouTube video featuring the sounds of a dark, ominous cello. I can’t tell you why the sounds of a somber cello made me tap into a grieving, Scottish mother caught in the spoils of War… but that is where the music took me.
I’ve been captivated by the Scottish heritage since I was a little girl. I don’t know much about my heritage since my father was adopted at a very early age. I do know I have a lineage tied to the Irish Scots who migrated to the Appalachian Mountains in the late 1800s. My family ( and my Father’s biological parents) and I are from central-eastern Kentucky.
Speaking of war, I remember a memory of my grandmother telling of my great-grandmother, on my gandaddy’s side. I never met her. Although that is who I am named after. During World War Two she had all 3 of her sons overseas in battle with Hitler’s troops as the United States stepped in. Thankfully, all 3 survived. My mother wouldn’t be here if my grandaddy had not survived and therefore I wouldn’t have been either.
My grandaddy and my granny were married shortly before he went off to war. Being a mother and wife I could not imagine the worry she and my granny went through. Not knowing if they were alive or dead until a letter came after months of silence. Both of them in fear of an empathetic soldier showing up at their door…. with their body or with just a folded flag to honor their courageous sacrifice.
My oldest child, now 16, my child was born female but does not identify as a young woman but a trans young man. He plans to join the Marines after graduation. So this fear is getting too close to home. What can I do except to be a supportive mother? I am very proud, don’t get me wrong, but as the tension rises with the times… I hear the promise of war screaming louder each coming year. I guess subconsciously I’m reaching out for some kind of understanding with my prose and notes.
My heart goes out to those who have had to experience this. Much love to all the veterans and to the families that fought an internal war while they defended our freedom.
I understand these notes are all over the place… but that is where my mind is at here recently. Focused on my Ancestry, my roots, my family, and my country, and resurrecting memories of my own and from another time entirely.
Thank you for allowing me to post to “Modern Women” I look forward to discussing and meeting others in this community.
As Always, Thank you for reading. :)