Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFD: Simplifying Experiments #276

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft

Conversation

leostera
Copy link
Contributor

@leostera leostera commented Dec 6, 2023

Hi folks 👋🏼 over the past few weeks we've had chats about the structure of the project, and some of the patterns in used in the code right now. Take this PR as an RFD (request for discussion), a little showcase of how we could simplify the codebase, cutting down on a lot of code, and make it easier to get into.

In particular, I'd like to bring attention to:

  • Named base models and wrapped types like Title.t
  • Query composition with fragments (and how to get rid of that UUID string slicing)
  • Using CC* modules instead of open Containers (or even opening containers by default everywhere)
  • And keeping types tight without compromising ergonomics

This version of the experiment library doesn't use any of the base models wrapped under field names and as such can fit the type definition, accessors, SQL fragments, and the SQL schema in a single module without much ceremony.

I tried working around some of the limitations of Caqti (which we discussed with @timohuber), but I think the best we can do without a major framework change is to colocate the schemas with the types they represent. If we see a pattern emerge, a ppx to derive SQL fragments from the records would be ideal. Will be good to upstream that to Caqti or publish it.

I've also made sure that every module corresponds to a file, especially if its going to be referenced from outside. This helps split compilation units, allows to include individual signatures, and should help with jump-to-definitions too. This is in contrast to the inline-module heavy style used around the codebase, which plenty of times needs several module jumps to find a definition.

I'll add some more directed comments in the PR in the morning, but I'd love to get your thoughts on this. Perhaps we can agree on a direction to take, and slowly move towards a simpler, more direct coding style.

Copy link
Contributor

@mabiede mabiede left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @leostera, especially the "repo" functions and caqti types look much cleaner!

I added a few questions or comments ;-)

Comment on lines +30 to +54
[@@deriving eq, show]

let id t = t.id
let title t = t.title
let public_title t = t.public_title
let description t = t.description
let cost_center t = t.cost_center
let organisational_unit t = t.organisational_unit
let filter t = t.filter
let contact_person_id t = t.contact_person_id
let smtp_auth_id t = t.smtp_auth_id
let direct_registration_disabled t = t.direct_registration_disabled
let registration_disabled t = t.registration_disabled
let allow_uninvited_signup t = t.allow_uninvited_signup
let external_data_required t = t.external_data_required
let show_external_data_id_links t = t.show_external_data_id_links
let experiment_type t = t.experiment_type
let email_session_reminder_lead_time t = t.email_session_reminder_lead_time
let invitation_reset_at t = t.invitation_reset_at
let created_at t = t.created_at
let updated_at t = t.updated_at

let text_message_session_reminder_lead_time t =
t.text_message_session_reminder_lead_time
;;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, the fields can be derived by using fields.

[@@deriving eq, show, fields]

@@ -0,0 +1,41 @@
(** Helper functions for creating Caqti types with custom encoder/decoders. *)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As these encoders are very general, they could be reused in other modules, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct! The idea would be to reuse them.

let public_title_placeholder = "###"

let sql_select_fragment =
[%string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed to evaluate the sql_select_fragments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, a few lines below we have:

     {sql|
        %{ Id.sql_select_fragment ~field:"pool_experiments.contact_person_uuid" },
        %{ Id.sql_select_fragment ~field:"pool_experiments.smtp_auth_uuid" },
        %{ Id.sql_select_fragment ~field:"pool_experiments.uuid" },
        ...
     |sql}

where are using this ppx to compose these strings without needing to always bring Format.sprintf

@@ -0,0 +1,25 @@
type t = Ptime.Span.t [@@deriving eq, show]

let make m = Ok m
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically let make = CCResult.return

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants