Sobes.tech
Senior

// Task 3 // Describe what problem this code solves // What problems are there in this solution? // How would you rewrite this code? var c int type Trace struct { // Some fields here } type Sender interface { Send(Trace) } func Do(sender Sender, tr Trace) { c++ if c == 100 { sender.Send(tr) c = 0 } }

sobes.tech AI

Answer from AI

This code solves the problem of periodically sending a Trace object through the Sender interface after accumulating 100 calls to the Do function.

Problems with this solution:

  1. Global variable c: Using a global variable to count calls is not thread-safe and can lead to data races when Do is called in parallel.
  2. Lack of synchronization: There are no mutexes or other protection mechanisms, making the code unsafe in a multithreaded environment.
  3. Rigid logic: Sending occurs exactly on the 100th call, with no flexibility to change the threshold or reset the counter.
  4. No error handling: The Send method does not return an error, and it cannot be handled.

How to rewrite:

  • Encapsulate the counter in a structure with a mutex for thread safety.
  • Make the send threshold configurable.
  • Add error handling.

Example of rewritten code:

 type Trace struct {
    // fields
 }

 type Sender interface {
    Send(Trace) error
 }

 type SenderWithCounter struct {
    sender Sender
    count  int
    limit  int
    mu     sync.Mutex
 }

 func NewSenderWithCounter(s Sender, limit int) *SenderWithCounter {
    return &SenderWithCounter{sender: s, limit: limit}
 }

 func (swc *SenderWithCounter) Do(tr Trace) error {
    swc.mu.Lock()
    defer swc.mu.Unlock()

    swc.count++
    if swc.count >= swc.limit {
        err := swc.sender.Send(tr)
        if err != nil {
            return err
        }
        swc.count = 0
    }
    return nil
 }

This approach ensures safety in concurrent use and flexible configuration.