0

I am a frontend developer (currently working with Vue and TS), and I have been searching for better organization of the frontend code and recently I got to know DDD a bit. I know DDD is mostly used for backend, but since it has some very nice ideias to it, I decided to give it a try and implement a little bit of frontend with DDD.

I have an interface that stands for the props of a component of mine: Cart.vue (components where the data flux passes by, repositories are called, and entities from the domain are instantiated, are stored in the application folder/layer):

export default interface CartProps {
  cart: {
    eventID: number
    products: Array<IBackendCartItemProps>
  }
}

And here the component, using Vue 2.7 Composition API:

...
import CartProps from './CartProps'

const props = defineProps<CartProps>()

let cart: Cart = reactive<Cart>(CartFactory.createCartFrom(props))
...

As you can see, I have a factory return me an instance of Cart (this one is an entity, stored inside the domain, under the Cart folder). The factory itself is also stored inside the domain, under the Cart folder, but it has a problem: the parameter I pass to the function is typed accordingly to what I expect from the backend, but this makes an object inside the domain (CartFactory.createCartFrom) based on an interface of the application (CartProps).

export default class CartFactory {
  public static createCartFrom({ cart }: CartProps): Cart {

    // implementation here

  }
}

One solution I can think of is to put the factory in the application folder. Although I know DDD is not a static folder structure, I haven't seen any factories outside the domain, far from the object they create, in the examples I checked out. So, if you can help, I'll be thankful.

EDIT 1:

My folder structure goes like this:

  • application (here I have the data flux inside components; the components themselves work as services)
    • Cart
      • helpers
      • CartProps.ts
      • Cart.vue
  • domain (here I have subdomains, like Cart, Recharge, etc)
    • Cart
      • interfaces
      • factories
        • CartFactory.ts
      • entities
        • Cart.ts
    • CartItem
      • interfaces
        • IBackendCartItemProps.ts
      • entities
        • CartItem.ts
  • infrastructure
  • ui (here I have ui Vue components, such as buttons, inputs, dialogs)
4
  • @DocBrown, I added the folder structure. I hope this helps. Sep 14, 2023 at 14:37
  • 1
    One of the most important insights DDD gave us is the use of a Ubiquitous Language. When you talk with your domain experts, do they often use BackendCartItemProps?
    – Rik D
    Sep 14, 2023 at 17:40
  • No, they don't. And that's precisely why I'd have to move this interface to the application. But still, then the factory would require an interface inside application, while the factory itself is in the domain. Sep 14, 2023 at 18:12
  • What if you cut-and-pasted CartProps.ts from the application folder to the domain folder? Or change the signature of your factory method: createCartFrom(eventID: number, products: IBackendCartItemProps[]). You don't even need "props" in your domain. Sep 18, 2023 at 15:46

2 Answers 2

1

I have to say your question is not easy to understand - a little bit of context about your domains would be good. From my limited knowledge about domain driven design, I would think, that the Cart in your frontend domain could exist inside its own bounded context and could be very different from the Cart that is made up of the cart properties that the backend delivers to you. So currently it could be only by coincidence, that these concepts are the same. I also think, that domain should not use entities from the application layer. Later if you decide to add features to your Cart in the frontend (e.g. selection states, or whatever) they could be different.

I would assume the correct thing to do would be, to define your own Cart Entity from a domain perspective and have the application layer which should do the "plumbing" translate your backend properties accordingly. So in that case you reversed the dependency.

2
  • I added the folder structure. I hope this helps you to understand it better. Sep 14, 2023 at 14:37
  • 1
    A Bounded Context is a part of the domain in which the ubiquitous language for that part is consistent. It’s a language boundary; the same word may have a different meaning (behavior) in another context. It has nothing to do with frontend/backend!
    – Rik D
    Sep 14, 2023 at 17:36
1

Instead of separate factory, you could create a static factory method inside the cart class.

This method takes in a collection of CartItem entities and returns a new Cart instance. Give it a meaningful name like LoadExisting.

In the Application you’ll have to convert the CartItems coming from the backend, into domain CartItem entities, so that you can pass those to the factory method in the cart entity.

7
  • Nice suggestion, but I believe the main problem is the parameter I'd pass to this LoadExisting be typed as an interface stored in the application, while the method is inside the domain. This way, I'd have a class inside the domain dependant on the something of the application. Sep 14, 2023 at 18:05
  • In the application you need to instantiate CartItems from the domain to pass those to the Cart.
    – Rik D
    Sep 14, 2023 at 19:12
  • Rik D, sorry, I don't follow what you said. Sep 14, 2023 at 19:15
  • I updated my answer, does that clarify it?
    – Rik D
    Sep 14, 2023 at 19:30
  • I need to instantiate the Cart, that contains Items. For Vue, it's a Cart component that has, inside of it, child components, and for the TS, it's a class, with an array of items. Sep 14, 2023 at 19:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.