[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f2whu5kd6dlxte":3,"$f1cmntyv9wpkl9":141},{"data":4},[5],{"id":6,"slug":7,"locale":8,"type":9,"title":10,"subtitle":11,"summary":12,"body":13,"primary_topic":14,"knowledge_status":15,"practical_validation":16,"workflow_status":17,"author_id":18,"published_at":19,"updated_at":19,"review_due_at":20,"canonical_url":21,"seo_title":10,"seo_description":12,"hero_asset_id":20,"reading_time":22,"version":23,"technology_versions":24,"review_frequency_days":25,"parent_content_id":26,"sort_in_parent":27,"hub_entry_status":28,"content_blocks":29,"hero_alt_text":21,"hero_caption":21,"hero_credit":21,"publication_scope":132,"access_level":133,"approved_at":134,"approved_by":135,"review_note":21,"home_enabled":136,"home_slot":137,"home_variant":138,"home_priority":27,"home_eyebrow":20,"home_valid_from":20,"home_valid_to":20,"home_image_asset_id":20,"promotion_kind":139,"sponsor_name":20,"sponsor_url":20,"sponsor_disclosure":140},"009c9da8-02a2-4bee-91fd-3e5320230f7e","modernizzazione-legacy-sanitario-hexagonal-ports-adapters","it","CAPSULE","Hexagonal Architecture: Ports & Adapters per servizi realmente sostituibili","Separare il dominio da database, broker, Mirth, PACS, viewer e protocolli esterni.","Ports & Adapters mette il dominio al centro e rende infrastruttura e integrazioni implementazioni sostituibili di contratti espliciti.","L'idea centrale\nLa Hexagonal Architecture, spesso chiamata Ports & Adapters, separa la logica di business da ciò che cambia più spesso: database, framework web, broker, protocolli, integration engine e sistemi esterni. Il dominio non «chiama Mirth» e non «legge Mongo»: chiede a una porta di pubblicare un ordine o di recuperare un paziente.\nInbound e outbound ports\nInbound Port: espone un caso d'uso del sistema, per esempio AdmitPatient, PlaceOrder o MergePatient.\n\nInbound Adapter: REST controller, consumer RabbitMQ, job schedulato o comando CLI che invoca il caso d'uso.\n\nOutbound Port: descrive una dipendenza necessaria al caso d'uso, per esempio PatientRepository, ImagingViewerPort o OrderIntegrationPort.\n\nOutbound Adapter: PostgreSQL, FHIR client, HL7\u002FMLLP, Mirth, VueMotion, DICOMweb o un adapter legacy.\n\nLa direzione delle dipendenze\nLe dipendenze di compilazione puntano verso il dominio. Il core definisce le interfacce che gli servono; l'infrastruttura le implementa. In questo modo cambiare database o provider non impone di riscrivere le regole clinico-amministrative.\nEsempio\nOrder Management può definire OrderPublisher.publish(OrderPlaced). In un'installazione l'adapter produce HL7 ORM via Mirth; in un'altra usa FHIR ServiceRequest; durante la migrazione un LegacyOrderAdapter può ancora chiamare il sistema precedente. Il dominio dell'ordine resta uguale.\nPerché è diverso da una classica architettura a layer\nIn una struttura Controller → Service → Repository è facile che Service importi client esterni e framework. Nell'architettura esagonale il confine è esplicito e verificabile: il domain module non deve dipendere dagli adapter. Test architetturali possono impedire regressioni.\nFHIR al confine\nFHIR è molto utile come formato di interoperabilità, ma non deve necessariamente diventare il modello interno di ogni bounded context. Un FhirAdapter può tradurre tra il modello di dominio e Patient, Encounter, ServiceRequest o Observation, mantenendo il core indipendente dalla versione e dai profili richiesti dal singolo contesto di integrazione.\nQuando non serve complicare\nPer un CRUD molto semplice senza regole e senza probabili sostituzioni, una struttura più diretta può bastare. Ports & Adapters crea valore soprattutto quando il dominio è importante e le dipendenze esterne sono numerose o variabili.\n\nLa prova pratica è semplice: il domain module dovrebbe poter essere testato senza database, rete, broker e integration engine.","58ba728e-da9d-409d-a6c7-31325e3773a8","REVIEWED","NOT_PERFORMED","PUBLISHED","fbbfd4b6-f4c7-4740-94a6-f81eb8fbb1b2","2026-08-25T18:15:01.950Z",null,"",8,3,{},365,"776fc737-dda9-4c82-bd56-b6ba0b7148d6",0,"AVAILABLE",[30,128],{"id":31,"type":32,"version":33,"doc":34},"46f66065-c987-5c41-83ed-03c881379c9d","rich_text",1,{"type":35,"content":36},"doc",[37,45,50,55,83,88,92,97,101,106,110,115,119,124],{"type":38,"attrs":39,"content":41},"heading",{"level":40},2,[42],{"type":43,"text":44},"text","L'idea centrale",{"type":46,"content":47},"paragraph",[48],{"type":43,"text":49},"La Hexagonal Architecture, spesso chiamata Ports & Adapters, separa la logica di business da ciò che cambia più spesso: database, framework web, broker, protocolli, integration engine e sistemi esterni. Il dominio non «chiama Mirth» e non «legge Mongo»: chiede a una porta di pubblicare un ordine o di recuperare un paziente.",{"type":38,"attrs":51,"content":52},{"level":40},[53],{"type":43,"text":54},"Inbound e outbound ports",{"type":56,"content":57},"bulletList",[58,65,71,77],{"type":59,"content":60},"listItem",[61],{"type":46,"content":62},[63],{"type":43,"text":64},"Inbound Port: espone un caso d'uso del sistema, per esempio AdmitPatient, PlaceOrder o MergePatient.",{"type":59,"content":66},[67],{"type":46,"content":68},[69],{"type":43,"text":70},"Inbound Adapter: REST controller, consumer RabbitMQ, job schedulato o comando CLI che invoca il caso d'uso.",{"type":59,"content":72},[73],{"type":46,"content":74},[75],{"type":43,"text":76},"Outbound Port: descrive una dipendenza necessaria al caso d'uso, per esempio PatientRepository, ImagingViewerPort o OrderIntegrationPort.",{"type":59,"content":78},[79],{"type":46,"content":80},[81],{"type":43,"text":82},"Outbound Adapter: PostgreSQL, FHIR client, HL7\u002FMLLP, Mirth, VueMotion, DICOMweb o un adapter legacy.",{"type":38,"attrs":84,"content":85},{"level":40},[86],{"type":43,"text":87},"La direzione delle dipendenze",{"type":46,"content":89},[90],{"type":43,"text":91},"Le dipendenze di compilazione puntano verso il dominio. Il core definisce le interfacce che gli servono; l'infrastruttura le implementa. In questo modo cambiare database o provider non impone di riscrivere le regole clinico-amministrative.",{"type":38,"attrs":93,"content":94},{"level":40},[95],{"type":43,"text":96},"Esempio",{"type":46,"content":98},[99],{"type":43,"text":100},"Order Management può definire OrderPublisher.publish(OrderPlaced). In un'installazione l'adapter produce HL7 ORM via Mirth; in un'altra usa FHIR ServiceRequest; durante la migrazione un LegacyOrderAdapter può ancora chiamare il sistema precedente. Il dominio dell'ordine resta uguale.",{"type":38,"attrs":102,"content":103},{"level":40},[104],{"type":43,"text":105},"Perché è diverso da una classica architettura a layer",{"type":46,"content":107},[108],{"type":43,"text":109},"In una struttura Controller → Service → Repository è facile che Service importi client esterni e framework. Nell'architettura esagonale il confine è esplicito e verificabile: il domain module non deve dipendere dagli adapter. Test architetturali possono impedire regressioni.",{"type":38,"attrs":111,"content":112},{"level":40},[113],{"type":43,"text":114},"FHIR al confine",{"type":46,"content":116},[117],{"type":43,"text":118},"FHIR è molto utile come formato di interoperabilità, ma non deve necessariamente diventare il modello interno di ogni bounded context. Un FhirAdapter può tradurre tra il modello di dominio e Patient, Encounter, ServiceRequest o Observation, mantenendo il core indipendente dalla versione e dai profili richiesti dal singolo contesto di integrazione.",{"type":38,"attrs":120,"content":121},{"level":40},[122],{"type":43,"text":123},"Quando non serve complicare",{"type":46,"content":125},[126],{"type":43,"text":127},"Per un CRUD molto semplice senza regole e senza probabili sostituzioni, una struttura più diretta può bastare. Ports & Adapters crea valore soprattutto quando il dominio è importante e le dipendenze esterne sono numerose o variabili.",{"id":129,"type":130,"version":33,"text":131},"89558085-5ec0-51c0-befa-cf3354439ce1","callout","La prova pratica è semplice: il domain module dovrebbe poter essere testato senza database, rete, broker e integration engine.","PORTAL","ANONYMOUS","2026-08-25T18:15:00.559Z","794a9185-136c-4415-ab23-cd144eb5870e",false,"LATEST","AUTO","EDITORIAL","Sponsorizzato",{"sources":142,"secondaryTopics":143,"tags":144,"primaryTopic":145,"technologies":149},[],[],[],[146],{"id":14,"name":147,"slug":148},"Software Architecture","software-architecture",[]]