DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Art Of Knowledge Crunching In Domain Driven Design
  • Prototype Pattern in JavaScript
  • Protect Your Invariants!
  • Having Fun with the Lightning Design System for React

Trending

  • Docker Base Images Demystified: A Practical Guide
  • How Large Tech Companies Architect Resilient Systems for Millions of Users
  • The Modern Data Stack Is Overrated — Here’s What Works
  • Unlocking AI Coding Assistants Part 4: Generate Spring Boot Application
  1. DZone
  2. Data Engineering
  3. Databases
  4. Domain-Driven Design in JavaScript

Domain-Driven Design in JavaScript

Let DDD bring order to your JavaScript chaos.

By 
Ewan Valentine user avatar
Ewan Valentine
·
Dec. 14, 18 · Tutorial
Likes (12)
Comment
Save
Tweet
Share
26.5K Views

Join the DZone community and get the full member experience.

Join For Free

I wouldn't class myself as a JavaScript developer, I always joke that it's a language I never meant to learn. It's so pervasive now, it just happened. I go through phases of enjoying it and despising it. But through the peaks and troughs of love and not quite hate. One problem persisted: if I'm to be a good JS developer and write functional JavaScript, how then do I write code in a way that implies a proper domain model?

In traditional OO languages, such as Java, C#, and even Go actually, it's easy to write code that's architected around a domain design. You have classes, which are big and do a lot of stuff. Which of course is something you generally avoid like the plague in JavaScript, for fair enough reasons.

However, my code always seemed to end up looking like this:

const { getUser, removeUser } = require('services/user');
const { sendEmail } = require('helpers/email');
const { pushNotification } = require('helpers/notifications');
const { removeFilesByUserId } = require('services/files');

const removeUserHandler = await (userId) => {
  const message = 'Your account has been deleted';
  try {
    const user = await getUser(userId);
    await removeUser(userId);
    await sendEmail(userId, message);
    await pushNotification(userId, message);
  } catch (e) {
    console.error(e);
    sendLogs('removeUserHandler', e);
  };
  return true;
};


This looks okay, right? Sure! No big problems here design-wise. However, when you have a large codebase entirely made up of files such as this, in other words directories full of vaguely grouped 'services,' individually exporting and importing single functions, often vaguely named, and not obviously belonging to a domain when reading through the code, it can very quickly feel as though you're dealing with a big ball of unrelated scripts, rather than a well-architected software application.

I didn't want to return to classes and traditional encapsulation. It felt like a step back after learning 'the functional way™️. But, increasingly, I was finding JavaScript projects difficult to read, 'bitty' and fragmented. I was seeing this everywhere, too! It wasn't just my own hapless downfall. It seemed really common to see JS projects with little to no design or architecture. I was ready to toss JS into the bin for good and resume my position in the Golang ivory tower.

Until one of my engineers slipped a new feature into one of our most noisy codebases, which jolted my attention.

Peering through reams and reams of JavaScript, suddenly something stood out in a PR.

ScheduledJobs.run(jobId);
const job = await ScheduledJobs.get(jobId);


Huh. Is that, a class? Surely not. We don't do that here! No!

const run = (jobId) => {};

const stop = (jobId) => {};

const pause = (jobId) => {};

const get = (jobId) => {};

module.exports = {
 run,
 stop,
 pause,
 get,
};


Praise Dijkstra, they're just functions! Good old-fashioned functions. Suddenly I felt so, so very silly for deliberating, Googling manically for weeks and weeks, and posting lengthy diatribes on Twitter about how JavaScript was done; not fit for public consumption. When all I needed to do was use what JavaScript gave me for this exact purpose: modules! I got so caught up in trying to follow a paradigm that I forgot to be pragmatic.

If I refactored my first arbitrary example to use this pattern, in order to follow a domain design, maybe I'd have something more like this:

const UserModel = require('models/user');
const EmailService = require('services/email');
const NotificationService = require('services/notification');
const FileModel = require('models/file');
const Logger = require('services/logger');

const removeUserHandler = await (userId) => {
  const message = 'Your account has been deleted';
  try {
    const user = await UserModel.getUser(userId);
    await UserModel.removeUser(userId);
    await EmailService.send(userId, message);
    await NotificationService.push(userId, message);
    return true;
  } catch (e) {
    console.error(e);
    Logger.send('removeUserHandler', e);
  };
  return true;
};


This code tells me so much more already!

I began writing my JavaScript in this way, centered around these objects of grouped functions, which can still be used in a functional way. But this pattern communicates purpose much better than dealing in lots of single, un-grouped function calls. I find it made code easier to follow, having that indicator of where this piece of code fits into the bigger picture.

It was so simple in the end, and it was something I already knew, even something I had already used hundreds of times in the past. It all seemed so obvious! But it's easy to neglect concepts such as DDD in languages like JavaScript, especially when you're on the pursuit to functional enlightenment! But there is a happy medium.

JavaScript Domain-driven design Design

Published at DZone with permission of Ewan Valentine, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Art Of Knowledge Crunching In Domain Driven Design
  • Prototype Pattern in JavaScript
  • Protect Your Invariants!
  • Having Fun with the Lightning Design System for React

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!