func GetLiveness
has a cyclomatic complexity of 18 with "high" risk 989// It is important to note that the values returned by the beacon node are not canonical;
990// they are best-effort and based upon a subjective view of the network.
991// A beacon node that was recently started or suffered a network partition may indicate that a validator is not live when it actually is.
992func (s *Server) GetLiveness(w http.ResponseWriter, r *http.Request) { 993 ctx, span := trace.StartSpan(r.Context(), "validator.GetLiveness")
994 defer span.End()
995
func GetSyncCommitteeDuties
has a cyclomatic complexity of 24 with "high" risk 856// or an epoch from the next sync committee period, then get the current state.
857// - Get the state's current sync committee. If it's an epoch from the next sync committee period, then get the next sync committee.
858// - Get duties.
859func (s *Server) GetSyncCommitteeDuties(w http.ResponseWriter, r *http.Request) { 860 ctx, span := trace.StartSpan(r.Context(), "validator.GetSyncCommitteeDuties")
861 defer span.End()
862
func GetProposerDuties
has a cyclomatic complexity of 20 with "high" risk 729}
730
731// GetProposerDuties requests beacon node to provide all validators that are scheduled to propose a block in the given epoch.
732func (s *Server) GetProposerDuties(w http.ResponseWriter, r *http.Request) { 733 ctx, span := trace.StartSpan(r.Context(), "validator.GetProposerDuties")
734 defer span.End()
735
func GetAttesterDuties
has a cyclomatic complexity of 21 with "high" risk 600
601// GetAttesterDuties requests the beacon node to provide a set of attestation duties,
602// which should be performed by validators, for a particular epoch.
603func (s *Server) GetAttesterDuties(w http.ResponseWriter, r *http.Request) { 604 ctx, span := trace.StartSpan(r.Context(), "validator.GetAttesterDuties")
605 defer span.End()
606
func SubmitBeaconCommitteeSubscription
has a cyclomatic complexity of 16 with "high" risk 308
309// SubmitBeaconCommitteeSubscription searches using discv5 for peers related to the provided subnet information
310// and replaces current peers with those ones if necessary.
311func (s *Server) SubmitBeaconCommitteeSubscription(w http.ResponseWriter, r *http.Request) { 312 ctx, span := trace.StartSpan(r.Context(), "validator.SubmitBeaconCommitteeSubscription")
313 defer span.End()
314
func SubmitSyncCommitteeSubscription
has a cyclomatic complexity of 18 with "high" risk 198// Subscribing to sync committee subnets is an action performed by VC to enable
199// network participation, and only required if the VC has an active
200// validator in an active sync committee.
201func (s *Server) SubmitSyncCommitteeSubscription(w http.ResponseWriter, r *http.Request) { 202 ctx, span := trace.StartSpan(r.Context(), "validator.SubmitSyncCommitteeSubscription")
203 defer span.End()
204
A function with high cyclomatic complexity can be hard to understand and maintain. Cyclomatic complexity is a software metric that measures the number of independent paths through a function. A higher cyclomatic complexity indicates that the function has more decision points and is more complex.
Functions with high cyclomatic complexity are more likely to have bugs and be harder to test. They may lead to reduced code maintainability and increased development time.
To reduce the cyclomatic complexity of a function, you can:
- Break the function into smaller, more manageable functions.
- Refactor complex logic into separate functions or classes.
- Avoid multiple return paths and deeply nested control expressions.
Bad practice
package main
import "log"
func fizzbuzzfuzz(x int) { // cc = 1
if x == 0 || x < 0 { // cc = 3 (if, ||)
return
}
for i := 1; i <= x; i++ { // cc = 4 (for)
switch i % 15 * 2 {
case 0: // cc = 5 (case)
countDiv3 += 1
countDiv5 += 1
log.Println("fizzbuzz")
break
case 3:
case 6:
case 9:
case 12: // cc = 9 (case)
countDiv3 += 1
log.Println("fizz")
break
case 5:
case 10: // cc = 11 (case)
countDiv5 += 1
log.Println("buzz")
break
default:
log.Printf("%d\n", x)
}
}
} // CC == 11; raises issues
Recommended
package main
import "log"
func fizzbuzz(x int) { // cc = 1
for i := 1; i <= x; i++ { // cc = 2 (for)
y := i%3 == 0
z := i%5 == 0
if y == z { // 3
if y == false { // 4
log.Printf("%d\n", i)
} else {
log.Println("fizzbuzz")
}
} else {
if y { // 5
log.Println("fizz")
} else {
log.Println("buzz")
}
}
}
} // CC == 5
Issue configuration
Cyclomatic complexity threshold can be configured using the
cyclomatic_complexity_threshold
(docs) in the
.deepsource.toml
config file.
Configuring this is optional. If you don't provide a value, the Analyzer will
raise issues for functions with complexity higher than the default threshold,
which is medium
(only raise issues for >15) for the Go Analyzer.
Here's the mapping of the risk category to the cyclomatic complexity score to help you configure this better:
Risk category | Cyclomatic complexity range | Recommended action |
---|---|---|
low | 1-5 | No action needed. |
medium | 6-15 | Review and monitor. |
high | 16-25 | Review and refactor. Recommended to add comments if the function is absolutely needed to be kept as it is. |
very-high. | 26-50 | Refactor to reduce the complexity. |
critical | >50 | Must refactor this. This can make the code untestable and very difficult to understand. |