Provide constructors for type instances #192

Open
opened 2025-12-28 18:07:23 +00:00 by sami · 1 comment
Owner

Originally created by @cthulhu-rider on GitHub (Aug 3, 2023).

there are several reasons, one of them https://github.com/nspcc-dev/neofs-sdk-go/pull/479#discussion_r1279235656

currently, we almost always initialize type instances via methods:

var t T
t.SetField(f)

one of the obvious disadvantages of this approach is the need to explain in the docs (and hope that a beginner will read it) mandatory methods, without which the instance remains invalid

one of the obvious advantages is readability:

var t T
t.SetEpoch(10)
t.SetCool(true)

// is clearer than
t := New(10, true)

it's proposed to provide constructors - functions with required parameters. For example, for signatures:

func New(signer Signer, data []byte) (Signature, error)
func NewSignatureFromV2(msg refs.Signature) (Signature, error)
func NewSignatureFromBytes(b []byte) (Signature, error)

with this Calculate / ReadFromV2 methods won't be needed (their use will remain in the reuse of the instance, but in practice this is rarely necessary)

t := New(a,b,c)
t.SetD(d) // optional
t.Sign(signer)

send(t)

// T must be signed.
func send(t T)

as we can see, we still need to write docs like must be signed and hope user will follow them. We can try to go further and make constructors finalizers, but that would require subtypes:

type BlankT struct{}
type T struct{}

t := NewBlank(a,b,c)
t.SetD(d) // optional

st := New(t BlankT, signer neofscrypto.Signer) (T, error)

func send(t T) // accepts signed entity by design

or with different naming

type T struct{}
type SignedT struct{}

t := New(a,b,c)
t.SetD(d) // optional

st := NewSigned(t BlankT, signer neofscrypto.Signer) (SignedT, error)

func send(t SignedT) // accepts signed entity by design
Originally created by @cthulhu-rider on GitHub (Aug 3, 2023). there are several reasons, one of them https://github.com/nspcc-dev/neofs-sdk-go/pull/479#discussion_r1279235656 currently, we almost always initialize type instances via methods: ```go var t T t.SetField(f) ``` one of the obvious disadvantages of this approach is the need to explain in the docs (and hope that a beginner will read it) mandatory methods, without which the instance remains invalid one of the obvious advantages is readability: ```go var t T t.SetEpoch(10) t.SetCool(true) // is clearer than t := New(10, true) ``` it's proposed to provide constructors - functions with required parameters. For example, for signatures: ``` func New(signer Signer, data []byte) (Signature, error) func NewSignatureFromV2(msg refs.Signature) (Signature, error) func NewSignatureFromBytes(b []byte) (Signature, error) ``` with this `Calculate` / `ReadFromV2` methods won't be needed (their use will remain in the reuse of the instance, but in practice this is rarely necessary) ```go t := New(a,b,c) t.SetD(d) // optional t.Sign(signer) send(t) // T must be signed. func send(t T) ``` as we can see, we still need to write docs like `must be signed` and hope user will follow them. We can try to go further and make constructors finalizers, but that would require subtypes: ```go type BlankT struct{} type T struct{} t := NewBlank(a,b,c) t.SetD(d) // optional st := New(t BlankT, signer neofscrypto.Signer) (T, error) func send(t T) // accepts signed entity by design ``` or with different naming ```go type T struct{} type SignedT struct{} t := New(a,b,c) t.SetD(d) // optional st := NewSigned(t BlankT, signer neofscrypto.Signer) (SignedT, error) func send(t SignedT) // accepts signed entity by design ```
Author
Owner

@cthulhu-rider commented on GitHub (Sep 12, 2023):

we may also provide decoding constructors

func NewFromBinary(b []byte) (T, error) {
  var t T
  return t, t.Unmarshal(b)
}

func NewFromJSON(j []byte) (T, error) {
  var t T
  return t, t.UnmarshalJSON(j)
}

and for some types

func NewFromString(s string) (T, error) {
  var t T
  return t, t.DecodeString(s)
}

could replace 2 instructions with 1 when there is no instance yet

@cthulhu-rider commented on GitHub (Sep 12, 2023): we may also provide decoding constructors ```go func NewFromBinary(b []byte) (T, error) { var t T return t, t.Unmarshal(b) } func NewFromJSON(j []byte) (T, error) { var t T return t, t.UnmarshalJSON(j) } ``` and for some types ```go func NewFromString(s string) (T, error) { var t T return t, t.DecodeString(s) } ``` could replace 2 instructions with 1 when there is no instance yet
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nspcc-dev/neofs-sdk-go#192
No description provided.