0

Take the following class, without [PublicAPI] attribute, ReSharper says that all public members can be made private.

using System;
using JetBrains.Annotations;

namespace ObjMtl
{
    // [PublicAPI]
    [NoReorder]
    public sealed class WavefrontMaterialColor
    {
        public float R;
        public float B;
        public float G;
        public float A = 1.0f;

        public float this[int index]
        {
            get => GetComponent(index);
            set => GetComponent(index) = value;
        }

        private ref float GetComponent(int index)
        {
            switch (index)
            {
                case 0: return ref R;
                case 1: return ref G;
                case 2: return ref B;
                case 3: return ref A;
                default: throw new ArgumentOutOfRangeException(nameof(index));
            }
        }
    }
}

This is nice but it's double-edged, while it filters the ambient noise from ReSharper, when adding it you also lose the overview of what could be hidden that may be an implementation detail. So, I used to add it quite often but then realized that it wasn't a good move since you hide many suggestions that may be worth applying later.

You could, instead of adding it to the class itself, add it to each members individually, but most of the time I found myself adding it to all members which is quite verbose to say the least. The only advantage in doing so is that should you add a member to the class, it won't immediately be seen as public because of the class-level attribute.

Now I'm on the other side, I'm considering not adding it all, but then you get tons of worthless suggestions, I guess you get the point...

Question:

What are some good metrics in deciding when a member should be declared part of the public API?

aybe
  • 727
  • 6
  • 16
  • 1
    "*ReSharper says that all public members can be made private*". That tells me you have no automated tests for that class. Because if you did have tests for the public parts of that class, then ReSharper would not complain. – David Arno Nov 23 '21 at 17:41
  • Makes a lot of sense actually, thanks! – aybe Nov 24 '21 at 13:28

1 Answers1

4

What are some good metrics in deciding when a member should be declared part of the public API?

When the class and it’s members are exposed to external clients.

When we declare a class and it’s members public, we define a contract for clients. The nature of a contract is that both parties have to comply with it. It cannot be changed one-sided. It is advised to keep the contract as narrow as possible, so it’s less likely the contract will break.

Specifically for properties, limiting access promotes encapsulation; public properties tends to cause knowledge duplication.

When the class is used inside the same project (solution), code inspection tools can determine which members are actually used, so we can limit the access to the unused members, making future changes easier.

But when the class is part of a library used by external clients, code inspection tools can no longer see if members are used or not. By using the PublicAPI annotation, the tooling knows not to warn us. That also means that as a developer you have to be extra careful which members you want to expose.

Note that the tooling gives some of the same warnings when reflection is used, for example for dependency injection. In that case you should annotate those classes or members with UsedImplicitly.

Rik D
  • 3,806
  • 2
  • 15
  • 26