Last active
May 16, 2020 01:15
-
-
Save daxfohl/0183db108924ee87440928cb803dcfc3 to your computer and use it in GitHub Desktop.
Simple SOA in F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Program | |
// A simple service | |
module PrinterService = | |
open System | |
// Helper functions first | |
// They can be public for easy unit testing, so long as they don't leave things inconsistent | |
let isObscene s = String.length s = 4 | |
let censor s = if isObscene s then String('*', s.Length) else s | |
let print s = printfn "%s" (censor s) | |
// Here's the interface that most consumers will use | |
type IPrinter = | |
abstract member Print : s:string -> unit | |
// The class is a thin wrapper around some funtions defined above | |
type Printer() = | |
interface IPrinter with | |
member __.Print s = print s | |
// A service depending on another | |
module AdderService = | |
open PrinterService | |
// Helper functions. I prefer curried style on simple functions with raw types, but tupled style otherwise. | |
let add x y = x + y | |
let addAndPrint(printer: IPrinter, x, y) = | |
let z = add x y | |
printer.Print(sprintf "%d+%d=%d" x y z) | |
z | |
// The interface | |
type IAdder = | |
abstract member Add: x:int * y:int -> int | |
// The class, note it takes the other service and then calls existing functions with it | |
// Also note it takes the other service as an interface, so easy mocking if desired | |
type Adder(printer: IPrinter) = | |
interface IAdder with | |
member __.Add(x, y) = addAndPrint(printer, x, y) | |
// The app itself | |
module App = | |
open PrinterService | |
open AdderService | |
// Note even the app is just a function, could be considered a library thing | |
let run(p: IPrinter, a: IAdder) = | |
p.Print("happy") | |
p.Print("asdf") | |
a.Add(2, 3) |> ignore | |
// Main | |
[<EntryPoint>] | |
let main _ = | |
// Main glues everything together and calls the app function | |
let p = PrinterService.Printer() | |
let a = AdderService.Adder(p) | |
App.run(p, a) | |
0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment