# Ocaml project structure and code correctness

**URL:** <https://discuss.ocaml.org/t/ocaml-project-structure-and-code-correctness/13280>\
**Category:** Learning\
**Tags:** opam, dune\
**Created:** [October 20, 2023, 12:06pm UTC](https://discuss.ocaml.org/t/ocaml-project-structure-and-code-correctness/13280 "2023-10-20T12:06:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![denis.gruiax](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/denis.gruiax/32/4804_2.png) [@denis.gruiax](https://discuss.ocaml.org/u/denis.gruiax)\
**Post date:** [October 20, 2023, 12:06pm UTC](https://discuss.ocaml.org/t/ocaml-project-structure-and-code-correctness/13280/1 "2023-10-20T12:06:56Z")

</div>

[binance-ocaml-api](https://github.com/denisgruiax/binance-ocaml-api)

I’m new to writing Ocaml code and have some design and code style issues.

The main problem is that I don’t think I’m very good at OCaml and I need some advice on how to design a big project like this and what mistakes I’ve made so far. The point is, if I can correct my design problems now, when the project is early on, there will be less to fix in the future.

Some of the questions are:

Working with Lwt is it ok for the API to return a value of type "a Lwt.t option? I make a module for each endpoint, is there a better way to structure those endpoints? I also need to know what kinds of mistakes I made now, like code style, correctness, and if there are parts of the code that don’t follow some rules? Using modules some of the endpoints have a lot of parameters, creating a module for every endpoint and fill all those parameters becomes harder for the user. Should I implement just the functions for the most used parameters?

I try to make the code more functional by using pure functions, higher order functions and reducing side effects as much as possible.

Any other advice is welcomed.

I tried to make the library as easy as possible to work with but as the project scales it becomes harder to work with.

---

<div class="post-metadata">

**Author:** ![jfeser](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jfeser/32/2093_2.png) [@jfeser](https://discuss.ocaml.org/u/jfeser)\
**Post date:** [October 20, 2023, 4:52pm UTC](https://discuss.ocaml.org/t/ocaml-project-structure-and-code-correctness/13280/2 "2023-10-20T16:52:56Z")

</div>

A few suggestions:

- I would enable ocamlformat. You can have your editor do the formatting, or you can run `dune build @fmt`.
- Using pure functions is a good instinct.
- I would avoid the use of functors in your endpoints. For example, I’d rewrite `margin_account_borrow.mli` to match the following interface:

```auto
open Variants

type parameters = {
    url : string;
    api_key : string;
    secret_key : string;
    asset : Symbol.t;
    recv_window : int;
}

val borrow : parameters -> float -> Wallet_transfer_direction.t -> int option Lwt.t
val isolated_borrow : parameters -> Symbol.t -> float -> Wallet_transfer_direction.t -> int option Lwt.t

```

- This will work nicely when most endpoints take the same parameters. If you want to use subtyping for the parameters, I would reach for first-class modules instead of functors:

```auto
open Variants

module type Parameters = sig
  val url : string
  val api_key : string
  val secret_key : string
  val asset : Symbol.t
  val recv_window : int
end

val borrow : (module Parameters) -> float -> Wallet_transfer_direction.t -> int option Lwt.t
val isolated_borrow : (module Parameters) -> Symbol.t -> float -> Wallet_transfer_direction.t -> int option Lwt.t

```

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [October 20, 2023, 4:57pm UTC](https://discuss.ocaml.org/t/ocaml-project-structure-and-code-correctness/13280/3 "2023-10-20T16:57:32Z")

</div>

One issue I am seeing is that you are using `float` for quantities and prices. IEEE 754 floats (like OCaml) suffer from the binary representation issue:

```auto
# 0.1 +. 0.2;;
- : float = 0.300000000000000044

```

I would recommend using a decimal floating point representation instead:

```auto
#require "ppx_decimal";;
#install_printer Decimal.pp;;
Decimal.(0.1m + 0.2m);;
- : Decimal.t = 0.3

```

---

<div class="post-metadata">

**Author:** ![denis.gruiax](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/denis.gruiax/32/4804_2.png) [@denis.gruiax](https://discuss.ocaml.org/u/denis.gruiax)\
**Post date:** [October 20, 2023, 5:19pm UTC](https://discuss.ocaml.org/t/ocaml-project-structure-and-code-correctness/13280/4 "2023-10-20T17:19:32Z")

</div>

Thanks, you are right. ✅  
Also I have some problems with conversion from float to string that I will fix with the Decimal module. 😅

---

<div class="post-metadata">

**Author:** ![denis.gruiax](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/denis.gruiax/32/4804_2.png) [@denis.gruiax](https://discuss.ocaml.org/u/denis.gruiax)\
**Post date:** [October 20, 2023, 5:23pm UTC](https://discuss.ocaml.org/t/ocaml-project-structure-and-code-correctness/13280/5 "2023-10-20T17:23:49Z")

</div>

Thanks, it makes sense. ✅  
It became harder to always make a new module when I could call the function directly with parameter from a specific API module.

I will start to refactor these modules and also add some optional parameters.
