1

I would like to make use of a external library to parse the core domain entities. Doing this in a naive way it would look like the following:

import { z } from 'zod';

const Audience = z.object({ name: z.string(), id: z.string(), });

type Audience = z.infer<typeof Audience>;

const buildMakeAudience = ({ getShortId }: { getShortId: () => string }) => { return (input: Audience) => {

const { id, name } = Audience.parse(input);

return Object.freeze({
  getId: () =&gt; id || getShortId(),
  getName: () =&gt; name,
});

}; };

export { buildMakeAudience };

However this breaks the dependency rule and our entities now depend on the 3rd party lib directly. I am interested to know if it is possible to use a 3rd party lib when defining the schema and types of your core domain entities, or if its best to just validate them by hand?

I could of course inject the parse() method, but to me this still feels heavily coupled to the external lib.

dendog
  • 201

1 Answers1

2

Clean architecture / onion architecture is not about avoiding dependencies on third party libraries. It's about being mindful of which components depend on what, and generally practicing dependency inversion so that external interfaces depend on your core business logic, not your core business logic on external components like a database layer.

Validation is typically part of your core business logic: it should not be possible to create an entity in an invalid state. How you implement this is up to you. If a third party library makes it easier to perform validation, using it sounds pretty sensible. A Zod schema is not like a database schema in that it would create a dependency on an external system, it is more like a way to conveniently handle Data Transfer Objects. And in order to achieve dependency inversion, the DTOs must be defined by the inner core/layer in an onion architecture, here your core business logic.

amon
  • 135,795