|
| 1 | +# Project details |
| 2 | +F# 9 |
| 3 | +C# 13 |
| 4 | +.NET 8 and 9 |
| 5 | +Nullability checks enabled |
| 6 | + |
| 7 | +## Libraries we use |
| 8 | + |
| 9 | +If you need any source code you can find it in the following repositories: |
| 10 | +[FParsec](https://github.com/stephan-tolksdorf/fparsec) `master` branch |
| 11 | +[XParsec](https://github.com/roboz0r/XParsec/) `main` branch |
| 12 | +[FSharp.Control.Reactive](https://github.com/fsprojects/FSharp.Control.Reactive) `master` branch |
| 13 | +[FSharp.Data.TypeProviders](https://github.com/fsprojects/FSharp.Data.TypeProviders) `main` branch |
| 14 | +[FSharp.SystemTextJson](https://github.com/Tarmil/FSharp.SystemTextJson.git) `master` branch |
| 15 | +[Oxpecker](https://github.com/Lanayx/Oxpecker.git) `main` branch |
| 16 | + |
| 17 | +# How to work with tests |
| 18 | + |
| 19 | +If you work with tests, then do not build the whole solution as it is large and the build happens very slow. |
| 20 | +Always try running tests with `--no-build` switch first to speedup execution. |
| 21 | +Instead run the tests individually or the whole test project. |
| 22 | +`CollectionAssert` cannot work with F# lists, only with F# array syntax |
| 23 | + |
| 24 | +# Code Style and Standards |
| 25 | + |
| 26 | +We prefer the latest F# 9 features over the old syntax |
| 27 | + |
| 28 | +Prefer `voption` over `option` |
| 29 | + |
| 30 | +Prefer `task` CE over `async` CE |
| 31 | + |
| 32 | +This is how you define a non-default F# class constructor: |
| 33 | +```fsharp |
| 34 | +type DerivedClass = |
| 35 | + inherit BaseClass |
| 36 | +
|
| 37 | + new (``arguments here``) as ``created object`` |
| 38 | + = |
| 39 | + // create any objects used in the base class constructor |
| 40 | + let fieldValue = "" |
| 41 | + { |
| 42 | + inherit |
| 43 | + BaseClass (``arguments here``) |
| 44 | + } |
| 45 | + then |
| 46 | + ``created object``.otherField <- fieldValue |
| 47 | +
|
| 48 | + [<DefaultValue>] |
| 49 | + val mutable otherField : FieldType |
| 50 | +``` |
| 51 | + |
| 52 | +Always prefer F# class initializers over property assignment! **You absolutely must use F# class initializers instead of property assignment**! |
| 53 | + |
| 54 | +Having a class declaration: |
| 55 | +``` F# |
| 56 | +type MyClass (someConstructorParam : string) = |
| 57 | + member ReadOnlyProperty = someConstructorParam |
| 58 | +
|
| 59 | + member val MutableProperty1 = "" with get, set |
| 60 | + member val MutableProperty2 = "" with get, set |
| 61 | +``` |
| 62 | + |
| 63 | +The following excerpt of class creation is wrong: |
| 64 | +``` F# |
| 65 | +let myClass = MyClass("some value") |
| 66 | +myClass.MutableProperty1 <- "new value" |
| 67 | +myClass.MutableProperty2 <- "new value" |
| 68 | +``` |
| 69 | + |
| 70 | +The following excerpt (uses initializer syntax) of class creation is right: |
| 71 | +``` F# |
| 72 | +let myClass = |
| 73 | + MyClass( |
| 74 | + // constructor parameters go first without names |
| 75 | + "some value", |
| 76 | + // then mutable properties go next with names |
| 77 | + MutableProperty1 = "new value", |
| 78 | + MutableProperty2 = |
| 79 | + // operations must be placed into parentheses |
| 80 | + (5 |> string) |
| 81 | + ) |
| 82 | +``` |
| 83 | + |
| 84 | +## Coding instructions |
| 85 | + |
| 86 | +During the implementation, if you need some types or members defined in the other project but that project is not referenced, then: |
| 87 | +1. stop implementing the solution; |
| 88 | +2. respond with summary about what is needed and which project it is defined in; |
| 89 | +3. ask if you can add the reference before continuing coding. |
| 90 | +Never ever duplicate the code unless you got explicit confirmation that you are allowed to do so. |
| 91 | + |
| 92 | +## Documentation and Naming |
| 93 | + |
| 94 | +* Document public APIs with XML comments |
| 95 | +* Use descriptive function names that indicate transformation direction |
| 96 | + |
| 97 | +# Build and test steps |
| 98 | + |
| 99 | +We use `dotnet test` CLI to test the project. |
| 100 | +If the build fails with errors or non-zero exit code, fix it based on the error messages given and repeat the build step. |
| 101 | +If build or tests step fails, fix the errors and repeat from build. After that, report all relevant build errors, error messages and specific details about failing tests and their test test failure details. |
| 102 | + |
| 103 | +## Fixing tests |
| 104 | + |
| 105 | +* If any of the tests fail: Check if the test, test expectation (either inline in the test or a reference file configured for the test) or implementation needs updating, and fix it |
| 106 | + |
| 107 | +## Acceptance criteria |
| 108 | + |
| 109 | +* Builds without errors. |
| 110 | +* Runs tests without errors. If some tests needed adjustments, those test expectations/baseline adjustments were done. |
| 111 | +* If the acceptance criteria was not met, collect the error messages (build failures or failing tests) and report them. |
0 commit comments