Le tue domande sono piuttosto ampie e non si può davvero rispondere senza fare molte ipotesi o dare molte alternative e considerazioni. Dalle domande sembra che tu stia cercando delle regole su quale logica va dove. Questo è generalmente noto come stratificazione. Lo schema più comune consiste di tre livelli: UI; Business (applicazione) e dati (base). Questa risposta su SO e i link contenuti al suo interno, probabilmente ti aiuteranno nel tuo cammino.
Per quanto riguarda t0 1: la finestra di messaggio non deve essere visualizzata dai sottoservizi / funzioni. Le caselle di messaggio sono implementazioni specifiche dell'interfaccia utente e una preoccupazione per l'interfaccia utente. Il messaggio visualizzato dalla finestra di messaggio può naturalmente provenire dai sottoservizi / funzioni. Se il sottotitolo non restituisce direttamente un messaggio di errore ma un codice di errore, è opportuno avere un sub separato (nel livello applicazione) per restituire i messaggi in base a un codice di errore. Questo potrebbe far parte di un servizio di "localizzazione" separato quando si ha a che fare con un'interfaccia utente multilingue.
Riguardo a 2: dipende. Possono generare eccezioni o possono contenerle e restituire un codice di errore. Se si sta anche prendendo in considerazione la possibilità di inserire sottoselezioni / funzioni in un modulo separato (exe o dll): le eccezioni non dovrebbero mai superare i limiti del modulo. In quel caso che contiene eccezioni e codici di errore restituiti è la strada da percorrere.
Riguardo a 3: L'interfaccia utente può avere una logica, ma quella logica dovrebbe essere limitata all'interfaccia utente, come l'attivazione e la disattivazione dei controlli. La convalida è un problema aziendale / di dominio / dell'applicazione e l'interfaccia utente dovrebbe rimandare a quel livello. Ovviamente dovrebbe avere una logica, incluse le istruzioni if :-) per elaborare i risultati di tale convalida e rifletterli nell'interfaccia utente.