├── .gitignore ├── Benchmarks.fs ├── CleanCode.fsproj ├── CompactDU.fs ├── Constants.fs ├── DU.fs ├── DUWithValues.fs ├── Inheritance.fs ├── Interface.fs ├── Program.fs ├── README.md ├── SeparateShapes.fs └── StructDU.fs /.gitignore: -------------------------------------------------------------------------------- 1 | .fable/ 2 | *.fs.js 3 | *.fs.js.map 4 | .fake/ 5 | .farmer/ 6 | .idea/ 7 | .ionide/ 8 | .vs/ 9 | deploy/ 10 | obj/ 11 | bin/ 12 | output/ 13 | packages/ 14 | paket-files/ 15 | node_modules/ 16 | release.cmd 17 | release.sh 18 | *.orig 19 | *.DotSettings.user 20 | **/BenchmarkDotNet.Artifacts/ 21 | -------------------------------------------------------------------------------- /Benchmarks.fs: -------------------------------------------------------------------------------- 1 | namespace CleanCode.Benchmarks 2 | 3 | open BenchmarkDotNet.Diagnosers 4 | open BenchmarkDotNet.Attributes 5 | open CleanCode 6 | 7 | [] 9 | [] 10 | type Benchmarks () = 11 | 12 | let duShapes = DU.shapes |> Array.copy 13 | 14 | [] 15 | member _.Inheritance () = 16 | 17 | let mutable acc = 0.0f 18 | 19 | for shape in Inheritance.shapes do 20 | acc <- acc + (shape.Area() / (1.0f + shape.CornerCount())) 21 | 22 | acc 23 | 24 | [] 25 | member _.Interface () = 26 | 27 | let mutable acc = 0.0f 28 | 29 | for shape in Interface.shapes do 30 | acc <- acc + (shape.Area() / (1.0f + shape.CornerCount())) 31 | 32 | acc 33 | 34 | [] 35 | member _.DU () = 36 | 37 | let mutable acc = 0.0f 38 | 39 | for shape in DU.shapes do 40 | acc <- acc + (DU.Shape.area shape / (1.0f + DU.Shape.cornerCount shape)) 41 | 42 | acc 43 | 44 | [] 45 | member _.DUWithValues () = 46 | let mutable acc = 0.0f 47 | for shape in DUWithValues.shapes do 48 | acc <- acc + (DUWithValues.Shape.area shape / (1.0f + DUWithValues.Shape.cornerCount shape)) 49 | 50 | acc 51 | 52 | [] 53 | member _.AltDULoop () = 54 | 55 | let circleCoef = Constants.pi / (1.0f + DU.Circle.cornerCount) 56 | let squareCoef = 1.0f / (1.0f + DU.Square.cornerCount) 57 | let rectangleCoef = 1.0f / (1.0f + DU.Rectangle.cornerCount) 58 | let triangleCoef = 0.5f / (1.0f + DU.Triangle.cornerCount) 59 | 60 | let mutable acc = 0.0f 61 | 62 | for shape in duShapes do 63 | acc <- acc + 64 | match shape with 65 | | DU.Shape.Circle circle -> 66 | circleCoef * (DU.Circle.area circle) 67 | | DU.Shape.Square square -> 68 | squareCoef * (DU.Square.area square) 69 | | DU.Shape.Rectangle rectangle -> 70 | rectangleCoef * (DU.Rectangle.area rectangle) 71 | | DU.Shape.Triangle triangle -> 72 | triangleCoef * (DU.Triangle.area triangle) 73 | 74 | acc 75 | 76 | [] 77 | member _.StructDU () = 78 | 79 | let circleCoef = Constants.pi / (1.0f + StructDU.Circle.cornerCount) 80 | let squareCoef = 1.0f / (1.0f + StructDU.Square.cornerCount) 81 | let rectangleCoef = 1.0f / (1.0f + StructDU.Rectangle.cornerCount) 82 | let triangleCoef = 0.5f / (1.0f + StructDU.Triangle.cornerCount) 83 | 84 | let mutable acc = 0.0f 85 | 86 | for shape in StructDU.shapes do 87 | acc <- acc + 88 | match shape with 89 | | StructDU.Shape.Circle circle -> 90 | circleCoef * (StructDU.Circle.area circle) 91 | | StructDU.Shape.Square square -> 92 | squareCoef * (StructDU.Square.area square) 93 | | StructDU.Shape.Rectangle rectangle -> 94 | rectangleCoef * (StructDU.Rectangle.area rectangle) 95 | | StructDU.Shape.Triangle triangle -> 96 | triangleCoef * (StructDU.Triangle.area triangle) 97 | 98 | acc 99 | 100 | [] 101 | member _.CompactDU () = 102 | 103 | let circleCoef = Constants.pi / (1.0f + CompactDU.Circle.cornerCount) 104 | let squareCoef = 1.0f / (1.0f + CompactDU.Square.cornerCount) 105 | let rectangleCoef = 1.0f / (1.0f + CompactDU.Rectangle.cornerCount) 106 | let triangleCoef = 0.5f / (1.0f + CompactDU.Triangle.cornerCount) 107 | 108 | let mutable acc = 0.0f 109 | 110 | for shape in CompactDU.shapes do 111 | let measures = shape.Measures 112 | acc <- acc + 113 | match shape.Type with 114 | | CompactDU.ShapeType.Circle -> 115 | circleCoef * (measures.Measure1 * measures.Measure1) 116 | | CompactDU.ShapeType.Square -> 117 | squareCoef * (measures.Measure1 * measures.Measure1) 118 | | CompactDU.ShapeType.Rectangle -> 119 | rectangleCoef * (measures.Measure1 * measures.Measure2) 120 | | CompactDU.ShapeType.Triangle -> 121 | triangleCoef * (0.5f * measures.Measure1 * measures.Measure2) 122 | 123 | acc 124 | 125 | [] 126 | member _.AltCompactDULoop () = 127 | 128 | let circleCoef = Constants.pi / (1.0f + CompactDU.Circle.cornerCount) 129 | let squareCoef = 1.0f / (1.0f + CompactDU.Square.cornerCount) 130 | let rectangleCoef = 1.0f / (1.0f + CompactDU.Rectangle.cornerCount) 131 | let triangleCoef = 0.5f / (1.0f + CompactDU.Triangle.cornerCount) 132 | 133 | let coefs = 134 | [| 135 | circleCoef 136 | squareCoef 137 | rectangleCoef 138 | triangleCoef 139 | |] 140 | 141 | let mutable acc = 0.0f 142 | 143 | for shape in CompactDU.shapes do 144 | let shapeType = int shape.Type 145 | let measures = shape.Measures 146 | acc <- acc + coefs[shapeType] * measures.Measure1 * measures.Measure2 147 | 148 | acc 149 | 150 | [] 151 | member _.SeparateShapes () = 152 | 153 | let circleCoef = Constants.pi / (1.0f + SeparateShapes.Circle.cornerCount) 154 | let squareCoef = 1.0f / (1.0f + SeparateShapes.Square.cornerCount) 155 | let rectangleCoef = 1.0f / (1.0f + SeparateShapes.Rectangle.cornerCount) 156 | let triangleCoef = 0.5f / (1.0f + SeparateShapes.Triangle.cornerCount) 157 | 158 | let mutable acc = 0.0f 159 | let shapes = SeparateShapes.shapes 160 | 161 | for circle in shapes.Circles do 162 | acc <- acc + circleCoef * (SeparateShapes.Circle.area circle) 163 | 164 | for square in shapes.Squares do 165 | acc <- acc + squareCoef * (SeparateShapes.Square.area square) 166 | 167 | for rectangle in shapes.Rectangles do 168 | acc <- acc + rectangleCoef * (SeparateShapes.Rectangle.area rectangle) 169 | 170 | for triangle in shapes.Triangles do 171 | acc <- acc + triangleCoef * (SeparateShapes.Triangle.area triangle) 172 | 173 | acc 174 | -------------------------------------------------------------------------------- /CleanCode.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net7.0 6 | x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /CompactDU.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.CompactDU 2 | 3 | open Microsoft.FSharp.Core 4 | 5 | [] 6 | type Measures = 7 | { 8 | Measure1: float32 9 | Measure2: float32 10 | } 11 | 12 | [] 13 | type ShapeType = 14 | | Circle = 0 15 | | Square = 1 16 | | Rectangle = 2 17 | | Triangle = 3 18 | 19 | module Circle = 20 | let cornerCount = 0.0f 21 | 22 | module Square = 23 | let cornerCount = 4.0f 24 | 25 | module Rectangle = 26 | let cornerCount = 4.0f 27 | 28 | module Triangle = 29 | let cornerCount = 3.0f 30 | 31 | [] 32 | type Shape = 33 | { 34 | Type: ShapeType 35 | Measures: Measures 36 | } 37 | 38 | module Shape = 39 | 40 | module Circle = 41 | 42 | let create (radius: float32) = 43 | let measures = { 44 | Measure1 = radius 45 | Measure2 = radius 46 | } 47 | { 48 | Type = ShapeType.Circle 49 | Measures = measures 50 | } 51 | 52 | module Square = 53 | 54 | let create (length: float32) = 55 | let measures = { 56 | Measure1 = length 57 | Measure2 = length 58 | } 59 | { 60 | Type = ShapeType.Square 61 | Measures = measures 62 | } 63 | 64 | module Rectangle = 65 | 66 | let create (width: float32) (height: float32) = 67 | let measures = { 68 | Measure1 = width 69 | Measure2 = height 70 | } 71 | { 72 | Type = ShapeType.Rectangle 73 | Measures = measures 74 | } 75 | 76 | module Triangle = 77 | 78 | let create (width: float32) (height: float32) = 79 | let measures = { 80 | Measure1 = width 81 | Measure2 = height 82 | } 83 | { 84 | Type = ShapeType.Triangle 85 | Measures = measures 86 | } 87 | 88 | 89 | let shapes = 90 | [| for shape in Inheritance.shapes do 91 | match shape with 92 | | :? Inheritance.Circle as c -> 93 | Shape.Circle.create c.Radius 94 | | :? Inheritance.Square as s -> 95 | Shape.Square.create s.Length 96 | | :? Inheritance.Rectangle as r -> 97 | Shape.Rectangle.create r.Width r.Height 98 | | :? Inheritance.Triangle as t -> 99 | Shape.Triangle.create t.Width t.Height 100 | | _ -> 101 | failwith "Unknown subtype" 102 | |] 103 | -------------------------------------------------------------------------------- /Constants.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.Constants 2 | 3 | let pi = float32 System.Math.PI 4 | -------------------------------------------------------------------------------- /DU.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.DU 2 | 3 | 4 | type Circle = 5 | { 6 | Radius: float32 7 | } 8 | 9 | module Circle = 10 | 11 | let create radius = 12 | { Radius = radius } 13 | 14 | let area c = 15 | c.Radius * c.Radius * Constants.pi 16 | 17 | let cornerCount = 0.0f 18 | 19 | type Square = 20 | { 21 | Length: float32 22 | } 23 | 24 | module Square = 25 | 26 | let create length = 27 | { Length = length } 28 | 29 | let area s = 30 | s.Length * s.Length 31 | 32 | let cornerCount = 4.0f 33 | 34 | type Rectangle = 35 | { 36 | Width: float32 37 | Height: float32 38 | } 39 | 40 | module Rectangle = 41 | 42 | let create width height = 43 | { 44 | Width = width 45 | Height = height 46 | } 47 | 48 | let area r = 49 | r.Width * r.Height 50 | 51 | let cornerCount = 4.0f 52 | 53 | type Triangle = 54 | { 55 | Width: float32 56 | Height: float32 57 | } 58 | 59 | module Triangle = 60 | 61 | let create width height = 62 | { 63 | Width = width 64 | Height = height 65 | } 66 | 67 | let area t = 68 | t.Width * t.Height * 0.5f 69 | 70 | let cornerCount = 3.0f 71 | 72 | [] 73 | type Shape = 74 | | Circle of Circle 75 | | Square of Square 76 | | Rectangle of Rectangle 77 | | Triangle of Triangle 78 | 79 | module Shape = 80 | 81 | let area = function 82 | | Shape.Circle c -> Circle.area c 83 | | Shape.Square s -> Square.area s 84 | | Shape.Rectangle r -> Rectangle.area r 85 | | Shape.Triangle t -> Triangle.area t 86 | 87 | let cornerCount = function 88 | | Shape.Circle _ -> 0.0f 89 | | Shape.Square _ -> 4.0f 90 | | Shape.Rectangle _ -> 4.0f 91 | | Shape.Triangle _ -> 3.0f 92 | 93 | let shapes = 94 | [| for shape in Inheritance.shapes do 95 | match shape with 96 | | :? Inheritance.Circle as c -> 97 | Circle.create c.Radius 98 | |> Shape.Circle 99 | | :? Inheritance.Square as s -> 100 | Square.create s.Length 101 | |> Shape.Square 102 | | :? Inheritance.Rectangle as r -> 103 | Rectangle.create r.Width r.Height 104 | |> Shape.Rectangle 105 | | :? Inheritance.Triangle as t -> 106 | Triangle.create t.Width t.Height 107 | |> Shape.Triangle 108 | | _ -> 109 | failwith "Unknown subtype" 110 | |] 111 | -------------------------------------------------------------------------------- /DUWithValues.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.DUWithValues 2 | 3 | type Shape = 4 | | Circle of radius : float32 5 | | Square of side : float32 6 | | Rectangle of length : float32 * width : float32 7 | | Triangle of length : float32 * width : float32 8 | 9 | module Shape = 10 | let area = function 11 | | Circle r -> r * r * Constants.pi 12 | | Square s -> s * s 13 | | Rectangle (l, w) -> l * w 14 | | Triangle (l, w) -> l * w * 0.5f 15 | 16 | let cornerCount = function 17 | | Circle _ -> 0.0f 18 | | Square _ -> 4.0f 19 | | Rectangle _ -> 4.0f 20 | | Triangle _ -> 3.0f 21 | 22 | let shapes = 23 | [| 24 | for shape in Inheritance.shapes do 25 | match shape with 26 | | :? Inheritance.Circle as c -> 27 | Circle c.Radius 28 | | :? Inheritance.Square as s -> 29 | Square s.Length 30 | | :? Inheritance.Rectangle as r -> 31 | Rectangle (r.Width, r.Height) 32 | | :? Inheritance.Triangle as t -> 33 | Triangle (t.Width, t.Height) 34 | | _ -> 35 | failwith "Unknown subtype" 36 | |] -------------------------------------------------------------------------------- /Inheritance.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.Inheritance 2 | 3 | [] 4 | type Shape() = 5 | abstract member Area: unit -> float32 6 | abstract member CornerCount: unit -> float32 7 | 8 | type Circle (radius: float32) = 9 | inherit Shape () 10 | override c.Area () = (radius * radius) * Constants.pi 11 | override c.CornerCount () = 0.0f 12 | member _.Radius = radius 13 | 14 | type Square (length: float32) = 15 | inherit Shape () 16 | override c.Area () = length * length 17 | override c.CornerCount () = 4.0f 18 | member _.Length = length 19 | 20 | type Rectangle (width: float32, height: float32) = 21 | inherit Shape () 22 | override c.Area () = width * height 23 | override c.CornerCount () = 4.0f 24 | member _.Width = width 25 | member _.Height = height 26 | 27 | type Triangle (width: float32, height: float32) = 28 | inherit Shape () 29 | override c.Area () = 0.5f * width * height 30 | override c.CornerCount () = 3.0f 31 | member _.Width = width 32 | member _.Height = height 33 | 34 | let rng = System.Random 123 35 | let shapeCount = 1048576 36 | 37 | let shapes = 38 | [| for _ in 1..shapeCount do 39 | 40 | let shapeType = rng.NextDouble() 41 | if shapeType < 0.25 then 42 | // printfn "Circle" 43 | let radius = 1.0f + 10.0f * (rng.NextSingle ()) 44 | Circle radius 45 | :> Shape 46 | elif shapeType < 0.5 then 47 | // printfn "Square" 48 | let length = 1.0f + 10.0f * (rng.NextSingle()) 49 | Square length 50 | :> Shape 51 | elif shapeType < 0.75 then 52 | // printfn "Rectangle" 53 | let width = 1.0f + 10.0f * (rng.NextSingle()) 54 | let height = 1.0f + 10.0f * (rng.NextSingle()) 55 | Rectangle (width, height) 56 | :> Shape 57 | else 58 | // printfn "Triangle" 59 | let width = 1.0f + 10.0f * (rng.NextSingle()) 60 | let height = 1.0f + 10.0f * (rng.NextSingle()) 61 | Triangle (width, height) 62 | :> Shape 63 | |] 64 | -------------------------------------------------------------------------------- /Interface.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.Interface 2 | 3 | type IShape = 4 | abstract member Area: unit -> float32 5 | abstract member CornerCount: unit -> float32 6 | 7 | type Circle (radius: float32) = 8 | interface IShape with 9 | member _.Area () = (radius * radius) * Constants.pi 10 | member _.CornerCount () = 0.0f 11 | 12 | type Square (length: float32) = 13 | interface IShape with 14 | member _.Area () = length * length 15 | member _.CornerCount () = 4.0f 16 | 17 | type Rectangle (width: float32, height: float32) = 18 | interface IShape with 19 | member _.Area () = width * height 20 | member _.CornerCount () = 4.0f 21 | 22 | type Triangle (width: float32, height: float32) = 23 | interface IShape with 24 | member _.Area () = 0.5f * width * height 25 | member _.CornerCount () = 3.0f 26 | 27 | let shapes = 28 | [| for shape in Inheritance.shapes do 29 | match shape with 30 | | :? Inheritance.Circle as c -> 31 | Circle c.Radius :> IShape 32 | | :? Inheritance.Square as s -> 33 | Square s.Length :> IShape 34 | | :? Inheritance.Rectangle as r -> 35 | Rectangle (r.Width, r.Height) :> IShape 36 | | :? Inheritance.Triangle as t -> 37 | Triangle (t.Width, t.Height) :> IShape 38 | | _ -> 39 | failwith "Unknown subtype" 40 | |] 41 | -------------------------------------------------------------------------------- /Program.fs: -------------------------------------------------------------------------------- 1 | open BenchmarkDotNet.Running 2 | open CleanCode 3 | 4 | [] 5 | let main argv = 6 | let _ = BenchmarkRunner.Run() 7 | 1 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CleanCodeDiscussion 2 | 3 | This is the code for the video "Fast F#: 'Clean' Code Chat". To run it, you must open your Terminal with Admin privlidges to get the Hardware Counters. 4 | 5 | To run the benchmarks, open a Terminal with Admin privlidges and navigate to the directory with the `CleanCode.fsproj` file. Once you have navigated to that directory, enter `dotnet run -c Release` to run the benchmarks. 6 | -------------------------------------------------------------------------------- /SeparateShapes.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.SeparateShapes 2 | 3 | open System.Collections.Generic 4 | 5 | [] 6 | type Circle = 7 | { 8 | Radius: float32 9 | } 10 | 11 | module Circle = 12 | 13 | let create radius = 14 | { Radius = radius } 15 | 16 | let area c = 17 | c.Radius * c.Radius * Constants.pi 18 | 19 | let cornerCount = 0.0f 20 | 21 | [] 22 | type Square = 23 | { 24 | Length: float32 25 | } 26 | 27 | module Square = 28 | 29 | let create length = 30 | { Length = length } 31 | 32 | let area s = 33 | s.Length * s.Length 34 | 35 | let cornerCount = 4.0f 36 | 37 | [] 38 | type Rectangle = 39 | { 40 | Width: float32 41 | Height: float32 42 | } 43 | 44 | module Rectangle = 45 | 46 | let create width height = 47 | { 48 | Width = width 49 | Height = height 50 | } 51 | 52 | let area r = 53 | r.Width * r.Height 54 | 55 | let cornerCount = 4.0f 56 | 57 | [] 58 | type Triangle = 59 | { 60 | Width: float32 61 | Height: float32 62 | } 63 | 64 | module Triangle = 65 | 66 | let create width height = 67 | { 68 | Width = width 69 | Height = height 70 | } 71 | 72 | let area t = 73 | t.Width * t.Height * 0.5f 74 | 75 | let cornerCount = 3.0f 76 | 77 | type Shapes = 78 | { 79 | Circles: Circle[] 80 | Squares: Square[] 81 | Rectangles: Rectangle[] 82 | Triangles: Triangle[] 83 | } 84 | 85 | let shapes = 86 | let circles = Stack() 87 | let squares = Stack() 88 | let rectangles = Stack() 89 | let triangles = Stack() 90 | 91 | for shape in Inheritance.shapes do 92 | match shape with 93 | | :? Inheritance.Circle as c -> 94 | Circle.create c.Radius 95 | |> circles.Push 96 | | :? Inheritance.Square as s -> 97 | Square.create s.Length 98 | |> squares.Push 99 | | :? Inheritance.Rectangle as r -> 100 | Rectangle.create r.Width r.Height 101 | |> rectangles.Push 102 | | :? Inheritance.Triangle as t -> 103 | Triangle.create t.Width t.Height 104 | |> triangles.Push 105 | | _ -> 106 | failwith "Unknown subtype" 107 | 108 | { 109 | Circles = circles.ToArray() 110 | Squares = squares.ToArray() 111 | Rectangles = rectangles.ToArray() 112 | Triangles = triangles.ToArray() 113 | } 114 | -------------------------------------------------------------------------------- /StructDU.fs: -------------------------------------------------------------------------------- 1 | module CleanCode.StructDU 2 | 3 | [] 4 | type Circle = 5 | { 6 | Radius: float32 7 | } 8 | 9 | module Circle = 10 | 11 | let create radius = 12 | { Radius = radius } 13 | 14 | let area c = 15 | c.Radius * c.Radius * Constants.pi 16 | 17 | let cornerCount = 0.0f 18 | 19 | [] 20 | type Square = 21 | { 22 | Length: float32 23 | } 24 | 25 | module Square = 26 | 27 | let create length = 28 | { Length = length } 29 | 30 | let area s = 31 | s.Length * s.Length 32 | 33 | let cornerCount = 4.0f 34 | 35 | [] 36 | type Rectangle = 37 | { 38 | Width: float32 39 | Height: float32 40 | } 41 | 42 | module Rectangle = 43 | 44 | let create width height = 45 | { 46 | Width = width 47 | Height = height 48 | } 49 | 50 | let area r = 51 | r.Width * r.Height 52 | 53 | let cornerCount = 4.0f 54 | 55 | [] 56 | type Triangle = 57 | { 58 | Width: float32 59 | Height: float32 60 | } 61 | 62 | module Triangle = 63 | 64 | let create width height = 65 | { 66 | Width = width 67 | Height = height 68 | } 69 | 70 | let area t = 71 | t.Width * t.Height * 0.5f 72 | 73 | let cornerCount = 3.0f 74 | 75 | [] 76 | type Shape = 77 | | Circle of circle: Circle 78 | | Square of square: Square 79 | | Rectangle of rectangle: Rectangle 80 | | Triangle of triangle: Triangle 81 | 82 | module Shape = 83 | 84 | let area = function 85 | | Shape.Circle c -> Circle.area c 86 | | Shape.Square s -> Square.area s 87 | | Shape.Rectangle r -> Rectangle.area r 88 | | Shape.Triangle t -> Triangle.area t 89 | 90 | let shapes = 91 | [| for shape in Inheritance.shapes do 92 | match shape with 93 | | :? Inheritance.Circle as c -> 94 | Circle.create c.Radius 95 | |> Shape.Circle 96 | | :? Inheritance.Square as s -> 97 | Square.create s.Length 98 | |> Shape.Square 99 | | :? Inheritance.Rectangle as r -> 100 | Rectangle.create r.Width r.Height 101 | |> Shape.Rectangle 102 | | :? Inheritance.Triangle as t -> 103 | Triangle.create t.Width t.Height 104 | |> Shape.Triangle 105 | | _ -> 106 | failwith "Unknown subtype" 107 | |] 108 | --------------------------------------------------------------------------------