[{"data":1,"prerenderedAt":476},["ShallowReactive",2],{"page-\u002Fv1\u002Fcore\u002Fanti-patterns":3},{"id":4,"title":5,"body":6,"description":468,"extension":469,"meta":470,"navigation":471,"path":472,"seo":473,"stem":474,"__hash__":475},"content\u002Fv1\u002Fcore\u002Fanti-patterns.md","Anti-patterns",{"type":7,"value":8,"toc":459},"minimark",[9,13,17,22,203,207,287,291,379,383,430,434,437,443,446],[10,11,5],"h1",{"id":12},"anti-patterns",[14,15,16],"p",{},"Use this page as a review checklist. Each row names the smell, why it breaks replaceability, and the fix.",[18,19,21],"h2",{"id":20},"cross-module","Cross-module",[23,24,25,41],"table",{},[26,27,28],"thead",{},[29,30,31,35,38],"tr",{},[32,33,34],"th",{},"Anti-pattern",[32,36,37],{},"Why it is wrong",[32,39,40],{},"Fix",[42,43,44,56,74,85,96,113,124,142,160,174,188],"tbody",{},[29,45,46,50,53],{},[47,48,49],"td",{},"Use Case imports peer Domain \u002F Application",[47,51,52],{},"Couples compile graph to peer internals",[47,54,55],{},"Local ACL port + adapter, or Domain Event",[29,57,58,65,68],{},[47,59,60,61],{},"Use Case injects peer ",[62,63,64],"code",{},"*ModuleInterface",[47,66,67],{},"Same coupling; fails HTTP-replace test",[47,69,70,71],{},"Consumer-owned ",[62,72,73],{},"{Need}PortInterface",[29,75,76,79,82],{},[47,77,78],{},"UI imports peer ORM models to decide policy",[47,80,81],{},"Business rules leak into delivery",[47,83,84],{},"Call own Use Case; peer data via ACL",[29,86,87,90,93],{},[47,88,89],{},"Shared folder holds business enums “for reuse”",[47,91,92],{},"Shared becomes a distributed Domain",[47,94,95],{},"ACL \u002F Events; Shared is technical only",[29,97,98,101,104],{},[47,99,100],{},"Thin event with ID only; consumer re-fetches publisher Domain",[47,102,103],{},"Re-introduces sync coupling",[47,105,106,107,112],{},"Rich happy-path payload (",[108,109,111],"a",{"href":110},"\u002Fv1\u002Fcore\u002Fcross-module-events","events",")",[29,114,115,118,121],{},[47,116,117],{},"Listener calls publisher Use Case \u002F repository",[47,119,120],{},"Listener becomes an RPC client",[47,122,123],{},"Map from event payload → inbound Use Case",[29,125,126,132,135],{},[47,127,128,129,131],{},"God ",[62,130,64],{}," dumping the whole module",[47,133,134],{},"Unstable public API; hard to HTTP-replace",[47,136,137,138,112],{},"Thin capability façades (",[108,139,141],{"href":140},"\u002Fv1\u002Fcore\u002Fcross-module-contracts","contracts",[29,143,144,151,154],{},[47,145,146,147,150],{},"No ",[62,148,149],{},"eventId"," \u002F idempotency on consumers",[47,152,153],{},"Duplicate side effects under at-least-once delivery",[47,155,156],{},[108,157,159],{"href":158},"\u002Fv1\u002Fcore\u002Fevent-delivery","Event delivery",[29,161,162,165,168],{},[47,163,164],{},"One SQL transaction writing two modules’ tables",[47,166,167],{},"Hidden distributed transaction",[47,169,170],{},[108,171,173],{"href":172},"\u002Fv1\u002Fcore\u002Ftransactions-and-failures","Transactions",[29,175,176,179,182],{},[47,177,178],{},"ORM relations across module schemas for reports",[47,180,181],{},"Read-side coupling",[47,183,184],{},[108,185,187],{"href":186},"\u002Fv1\u002Fcore\u002Freads-and-reporting","Reads & reporting",[29,189,190,193,196],{},[47,191,192],{},"Orchestrator imports three Domains",[47,194,195],{},"Collapses boundaries",[47,197,198,202],{},[108,199,201],{"href":200},"\u002Fv1\u002Fcore\u002Forchestration","Orchestration"," — ACL\u002FEvents only",[18,204,206],{"id":205},"layers-and-ports","Layers and ports",[23,208,209,219],{},[26,210,211],{},[29,212,213,215,217],{},[32,214,34],{},[32,216,37],{},[32,218,40],{},[42,220,221,232,243,254,265,276],{},[29,222,223,226,229],{},[47,224,225],{},"Controller \u002F admin action calls repository directly",[47,227,228],{},"Skips orchestration; logic spreads",[47,230,231],{},"Controller → first-level Use Case",[29,233,234,237,240],{},[47,235,236],{},"Use Case uses ORM \u002F query builder",[47,238,239],{},"Application learns persistence shape",[47,241,242],{},"Domain repository port",[29,244,245,248,251],{},[47,246,247],{},"Entity extends ORM model",[47,249,250],{},"Domain inseparable from driver",[47,252,253],{},"Plain Entity + Infrastructure record",[29,255,256,259,262],{},[47,257,258],{},"Repository returns ORM models",[47,260,261],{},"Domain\u002FApplication polluted",[47,263,264],{},"Map to Entity \u002F Domain DTO",[29,266,267,270,273],{},[47,268,269],{},"Domain Event uses framework traits \u002F facades",[47,271,272],{},"Domain tied to host",[47,274,275],{},"Pure event + Shared dispatcher port",[29,277,278,281,284],{},[47,279,280],{},"Business rules inside composition root",[47,282,283],{},"Wiring layer grows a second Application",[47,285,286],{},"Move to Use Case \u002F Domain service",[18,288,290],{"id":289},"use-cases-and-dtos","Use Cases and DTOs",[23,292,293,303],{},[26,294,295],{},[29,296,297,299,301],{},[32,298,34],{},[32,300,37],{},[32,302,40],{},[42,304,305,324,342,353,364],{},[29,306,307,314,317],{},[47,308,309,310,313],{},"Literal ",[62,311,312],{},"Feature\u002F"," directory",[47,315,316],{},"Placeholder mistaken for real path",[47,318,319,320,323],{},"Real capability name (",[62,321,322],{},"Order\u002F",", …)",[29,325,326,332,335],{},[47,327,328,329],{},"UI calls nested helper under ",[62,330,331],{},"UseCases\u002F…\u002FProcessing",[47,333,334],{},"Breaks entry-point boundary",[47,336,337,338,341],{},"Call first-level ",[62,339,340],{},"*UseCase"," only",[29,343,344,347,350],{},[47,345,346],{},"Peer module calls this module’s Use Case",[47,348,349],{},"Breaks replaceability",[47,351,352],{},"ACL or Events",[29,354,355,358,361],{},[47,356,357],{},"Application DTO used as Domain-wide shared type across modules",[47,359,360],{},"Cross-module DTO coupling",[47,362,363],{},"Local DTOs; map at ACL boundary",[29,365,366,369,372],{},[47,367,368],{},"Many public methods on a Use Case",[47,370,371],{},"Unclear entry; hard to test",[47,373,374,375,378],{},"Single ",[62,376,377],{},"__invoke"," on first-level Use Cases",[18,380,382],{"id":381},"persistence-and-shared","Persistence and Shared",[23,384,385,395],{},[26,386,387],{},[29,388,389,391,393],{},[32,390,34],{},[32,392,37],{},[32,394,40],{},[42,396,397,408,419],{},[29,398,399,402,405],{},[47,400,401],{},"Cross-module foreign keys for business joins via ORM relations",[47,403,404],{},"Hidden coupling through the database",[47,406,407],{},"ACL reads \u002F Events; ownership per module",[29,409,410,413,416],{},[47,411,412],{},"Promote to Shared on first use “for the future”",[47,414,415],{},"Premature kernel",[47,417,418],{},"Keep in module until second consumer appears",[29,420,421,424,427],{},[47,422,423],{},"SQL \u002F vendor SDK inside Domain",[47,425,426],{},"Domain not portable",[47,428,429],{},"Port + Infrastructure adapter",[18,431,433],{"id":432},"design-test-final-gate","Design test (final gate)",[14,435,436],{},"Before merge, answer again:",[438,439,440],"blockquote",{},[14,441,442],{},"If the peer module is deleted and replaced by HTTP, does Application\u002FDomain still compile?",[14,444,445],{},"If not, you still have an anti-pattern above.",[14,447,448,449,453,454,458],{},"Return to the ",[108,450,452],{"href":451},"\u002Fv1\u002Fcore\u002Fdecision-tree","decision tree"," or walk the ",[108,455,457],{"href":456},"\u002Fv1\u002Fcookbook\u002Fordering-warehouse","Ordering ↔ Warehouse cookbook",".",{"title":460,"searchDepth":461,"depth":461,"links":462},"",2,[463,464,465,466,467],{"id":20,"depth":461,"text":21},{"id":205,"depth":461,"text":206},{"id":289,"depth":461,"text":290},{"id":381,"depth":461,"text":382},{"id":432,"depth":461,"text":433},"Common Modular Hexagonal DDD mistakes and the required fixes.","md",{},true,"\u002Fv1\u002Fcore\u002Fanti-patterns",{"title":5,"description":468},"v1\u002Fcore\u002Fanti-patterns","xoS1uiGBccqA_6f0dSG5HaC5Ftrp8QbVRjx-hBQ_Fhs",1786241412552]