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

Policy for naming public API functions/structs #189

Open
mabruzzo opened this issue Mar 27, 2024 · 1 comment
Open

Policy for naming public API functions/structs #189

mabruzzo opened this issue Mar 27, 2024 · 1 comment
Labels
Milestone

Comments

@mabruzzo
Copy link
Collaborator

Background

A common convention for C libraries is to use a common prefix in the names of all functions/types exported by a library.

  • openmp runtime libraries use the omp_ prefix (e.g. omp_get_num_threads)
  • MPI libraries use the MPI_ prefix (e.g. MPI_Send)
  • HDF5 uses the H5 prefix (e.g. H5Fopen, H5Dopen)
  • libpng uses the png_ prefix
  • FFTW uses the fftw_ prefix

This convention exists because C has a global namespace and problems obviously arise if 2 or more functions share the same name. (An added benefit is that it's really easy to see when your calling an "imported" function).

Currently, Grackle does not do this.

Proposal

While I don't think this has been a problem yet, I think this is something we should consider addressing (It may make grackle easier for new codes to adopt). There are 2 parts to this proposal.

Part A

I think we should adopt a policy that all newly defined public functions and types share some standardized prefix. I think that there are 2 obvious prefixes: gr_ (as in gr_float) OR grackle_. I favor the former because it's shorter and may make the new function names more readable.1

Part B

I think it may be worth renaming at least some of the existing stuff in the public API (even if we don't adopt a standard solution). We could do it in a backwards compatible manner like renaming performed in PR #139.

In particular, I think that names of the following groups of types/functions are generic enough to cause collisions2:

  1. the code_units struct
  2. set_velocity_units, get_velocity_units, get_temperature_units functions
  3. param_name_int, param_name_double, param_name_string

For completeness I've grouped the renaming api function/type names in order of decreasing concern (in the following spoiler tag). I don't think there's any urgency for renaming them (I could easily be convinced to do it -- but renaming more of the stuff probably means we would need to keep the deprecated versions around for a lot longer).

Spoiler warning
  1. solve_chemistry, calculate_cooling_time, calculate_dust_temperature, calculate_gamma, calculate_pressure, calculate_temperature
  2. the rates functions
  3. the local versions of the functions listed in group 4
  4. the chemistry_data2 and chemistry_data_storage structs and the associated functions are of little concern
  5. the structs internally stored by the chemistry_data_storage struct
  6. the get_grackle_version function is not a concern

I definitely would appreciate input on this

Footnotes

  1. Keep in mind that the standard only guarantees that the first 31 characters in an exported identifier are honored (mentioned here)

  2. Even if they don't cause collisions, these particular highlighted function names could definitely cause some confusion. If I were reading a downstream application for the first time, I might be surprised to learn that get_temperature_units is a grackle-specific function. 2

@brittonsmith brittonsmith added this to the 4.0 milestone Apr 25, 2024
mabruzzo added a commit to mabruzzo/grackle that referenced this issue Jun 3, 2024
This change was split off from GH PR grackle-project#197. This should be a lot easier
to review in isolation (and I think that it is a generally useful
change in its own right).

Overview
--------
The objective of this PR is conceptually very simple. It introduces the
following function:

```c++
int gr_initialize_field_data(grackle_field_data *my_fields);
```

The idea is to have users immediately call this function right after they
initialize a new `grackle_field_data` instance

- When it's called the handful of non data-field members are assigned
  sensible defaults. It also initializes all data-field members to NULL
  pointers.

- this is analogous to the way that `local_initialize_chemistry_parameters`
  is used.

Motivation
----------

While this function is not strictly necessary, I think it is a useful
addition and I think we should tell people to use it (though old code
won't break).

A large motivation is peace of mind. I have often wished for this sort
of thing. I'm always a little concerned when using a new configuration
of grackle that I didn't initialize all of the required fields. I
would definitely feel a little more comfortable knowing that a field
that I forgot about is assigned a ``NULL`` pointer rather than some
garbage data that might let the code chug along.

It could also facillitate more error checking:

- such as checks in the style of the ``grid_dx`` check introduced in
  PR grackle-project#190 (applying similar checks to `grid_rank`, `grid_dimension`,
  `grid_start`, and `grid_end` requires that we know their default
  value).

- we could explicitly check that the user specified all required
  data-fields. We can only do this if we know that unset data-fields
  have a default value of `NULL`.

  - **From a user friendliness perspective, I think this check alone is
    enough to justify the function's existence.**

  - We could also potentially warn if unnecessary fields were specified

  - Plus, we could account for the fact that functions like
    ``calculate_pressure`` require fewer fields that ``solve_chemistry``

- we could also add checks that none of the fields are aliases (an
  implicit Fortran requirement). This would be much easier to implement
  if we knew we could just ignore fields that were set to ``NULL``
  pointers

We would probably need to make these checks opt-in somehow, both because
we can't be absolutely certain whether a user actually invoked
``gr_initialize_field_data`` and users might not want the runtime-cost
(which could be relatively large for very small grids)

Naming
------

I choose to name this function based on my suggestion in grackle-project#189 that we
adopt a convention that all new functions in the stable public API share
a common prefix (`gr_` or `grackle_`).

For the sake of proposing something concrete, I assumed that we choose
the `gr_` prefix. (If we decide on a different prefix, this would be
easy to change).

Alternatively, if we don't want any prefix, we could name it
`initialize_grackle_field_data` (I do worry a little that could
introduce naming conflicts with existing functions in downstream codes)
mabruzzo added a commit to mabruzzo/grackle that referenced this issue Jun 3, 2024
This change was split off from GH PR grackle-project#197. This should be a lot easier
to review in isolation (and I think that it is a generally useful
change in its own right).

Overview
--------
The objective of this PR is conceptually very simple. It introduces the
following function:

```c++
int gr_initialize_field_data(grackle_field_data *my_fields);
```

The idea is to have users immediately call this function right after they
initialize a new `grackle_field_data` instance

- When it's called the handful of non data-field members are assigned
  sensible defaults. It also initializes all data-field members to NULL
  pointers.

- this is analogous to the way that `local_initialize_chemistry_parameters`
  is used.

Motivation
----------

While this function is not strictly necessary, I think it is a useful
addition and I think we should tell people to use it (though old code
won't break).

A large motivation is peace of mind. I have often wished for this sort
of thing. I'm always a little concerned when using a new configuration
of grackle that I didn't initialize all of the required fields. I
would definitely feel a little more comfortable knowing that a field
that I forgot about is assigned a ``NULL`` pointer rather than some
garbage data that might let the code chug along.

It could also facillitate more error checking:

- such as checks in the style of the ``grid_dx`` check introduced in
  PR grackle-project#190 (applying similar checks to `grid_rank`, `grid_dimension`,
  `grid_start`, and `grid_end` requires that we know their default
  value).

- we could explicitly check that the user specified all required
  data-fields. We can only do this if we know that unset data-fields
  have a default value of `NULL`.

  - **From a user friendliness perspective, I think this check alone is
    enough to justify the function's existence.**

  - We could also potentially warn if unnecessary fields were specified

  - Plus, we could account for the fact that functions like
    ``calculate_pressure`` require fewer fields that ``solve_chemistry``

- we could also add checks that none of the fields are aliases (an
  implicit Fortran requirement). This would be much easier to implement
  if we knew we could just ignore fields that were set to ``NULL``
  pointers

We would probably need to make these checks opt-in somehow, both because
we can't be absolutely certain whether a user actually invoked
``gr_initialize_field_data`` and users might not want the runtime-cost
(which could be relatively large for very small grids)

Naming
------

I choose to name this function based on my suggestion in grackle-project#189 that we
adopt a convention that all new functions in the stable public API share
a common prefix (`gr_` or `grackle_`).

For the sake of proposing something concrete, I assumed that we choose
the `gr_` prefix. (If we decide on a different prefix, this would be
easy to change).

Alternatively, if we don't want any prefix, we could name it
`initialize_grackle_field_data` (I do worry a little that could
introduce naming conflicts with existing functions in downstream codes)
@mabruzzo
Copy link
Collaborator Author

We discussed this today at the developer meeting. We have reached a consensus on adopting the gr_ prefix.

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

No branches or pull requests

2 participants