Code Simplicity

And practical ways to reduce complexity

Shai Boharon, Admin experiences team

Promise

  • Cyclomatic code complexity metric

  • Practical and simple ways to reduce code complexity

Why code Simplicity?

Focusing on the goal

Cyclomatic complexity

Start

For

Some code

Is divided by 7

End

Boom

Has

the digit 7

For end

function sevenBoom(limit) {
  for (let num = 0; num <= limit; num++) {
    const itDividesBySeven = !(num % 7)
    const hasSevenDigit = num.toString().includes("7")

    if (itDividesBySeven || hasSevenDigit) {
      console.log("Boom", {
        num,
      })
    }
  }
}

Calculate code complexity

Start

For

Some code

Is divided by 7

End

Boom

Has

the digit 7

For end

function sevenBoom(limit) {
  for (let num = 0; num <= limit; num++) {
    const itDividesBySeven = !(num % 7)
    const hasSevenDigit = num.toString().includes("7")

    if (itDividesBySeven || hasSevenDigit) {
      console.log("Boom", {
        num,
      })
    }
  }
}

Calculate code complexity

1

2

3

4

Indication in the code

If statement if(some_condition) { … }

Case statement case { ... }

While statement while(some_condition) { ... }

For statement for, for in,  for of

Catch statement catch(error) { .. }

Boolean operators  &&, ||

Ternary operator some_condition ? one_value : other_value

Optional chaining some_object?.some_property?.sub_property

Elvis operator variable = some_value ?? other_value

How to achieve simplicity

  • Awareness
  • Code design
  • Automatic tools

Code design

  • Preferring default values over null / undefined
  • Boolean algebraic
  • Preferring functional programming over for loops
  • Preferring promise over try catch, and minimal try-catch
  • Encapsulation of complexity
  • Polymorphism
  • Recognizing the need of Factory, Strategy and Command design pattern
  • Null object pattern
  • Maybe and Either functors

Anemic domain model OO anti-pattern

interface ISegmentGroup {
    id?: string;
    name?: string;
    provider?: string;
    size?: number;
    cost?: number;
}

function getSegmentName(segment: ISegmentGroup): string {
    // complexity of 7
    if (segment?.name && segment?.provider) {
        return segment?.name + segment?.provider;
    }
    return null;
}

function getSegmentCost(segment: ISegmentGroup): number {
    // complexity of 5
    return (segment?.size ?? 0) * (segment?.cost ?? 0);
}

Default values (and Null object pattern)

class SegmentGroup implements ISegmentGroup {
    id: string;
    name: string;
    provider: string;
    size: number;
    cost: number;
    constructor(
        {
            id = '',
            name = '',
            provider = '',
            size = 0,
            cost = 0,
        }: Partial<ISegmentGroup> = {} as Partial<ISegmentGroup>
    ) {
        this.id = id;
        this.name = name;
        this.provider = provider;
        this.size = size;
        this.cost = cost;
    }

    isEmpty() {
        // complexity of 1
        return !!this.id;
    }

    getSegmentName() {
        // complexity of 1
        return this.name + this.provider;
    }

    getSegmentCost() {
        // complexity of 1
        return this.size * this.cost;
    }
}
interface ISegmentGroup {
    id: string
    name: string
    provider: string
    size: number
    cost: number
}
// eslint-disable-next-line complexity
export const getSelectedFeatures = (
	featuresService: FeaturesService,
	flavorService: IAppFlavorService,
	tenantContext: TenantContext,
	tenantsContext: TenantsContext,
	tvmLicensesService: TvmLicensesService,
	msecHost: IMsecHostService
): SelectedFeatures => {
	const isMultiTenantOrg = msecHost.mto.isMTO();
	const isReflectDeviceIsolationStatus = featuresService.isEnabled(Feature.ReflectDeviceIsolationStatus);
	const isMdeWithSccmEnabled = featuresService.isEnabled(Feature.EndpointConfigManagementMdeWithSccm);
	const isDeviceRoleEnabled = featuresService.isEnabled(Feature.MagellanDeviceRoleColumn);
	const isCAPExperiencesEnabled = featuresService.isAnyEnabled([
		Feature.MagellanCapExperiences,
		Feature.XspmPrivatePreview1,
		Feature.XspmPrivatePreview2,
		Feature.XspmPrivatePreview3,
		Feature.XspmPublicPreview,
	]);
	const isSetCriticalityLevelEnabled =
		!isMultiTenantOrg && flavorService.isEnabled(AppFlavorConfig.devices.criticalityLevel);
	const isDiscoverySourceEnabled =
		!isMultiTenantOrg &&
		featuresService.isAnyEnabled([
			Feature.MagellanDeviceInventoryDiscoverySource,
			Feature.DataConnectorsQualys,
			Feature.DataConnectorsServiceNowCmdb,
			Feature.DataConnectorsRapid7,
		]);
	const hasOnboardingStatusLicense = flavorService.isEnabled(AppFlavorConfig.devices.onboardingStatus);
	const hasIotLicense = flavorService.isEnabled(AppFlavorConfig.devices.iotDevices);
	const hasNetworkTabLicense = flavorService.isEnabled(AppFlavorConfig.devices.networkTab);
	const hasTvmBasicLicense = tvmLicensesService.isEnabled(TvmLicenseType.TvmBasic);
	const magellanOptOut = tenantContext?.MagellanOptOut;
	const isNetworkTabEnabled = hasNetworkTabLicense || hasTvmBasicLicense;
	const isReportInaccuracyEnabled = featuresService.isEnabled(Feature.TvmFeedbackV2);
	const isExportEnabled = !isMultiTenantOrg;
	const isGoToNetworkDevicesScanSettingsEnabled = !isMultiTenantOrg;
 ...
	return {
		isMultiTenantOrg,
		withNetworkDevicesTab,
		isMdeWithSccmEnabled,
		withNetworkDeviceType: !withNetworkDevicesTab,
		withIotTab,
		isOnboardingStatusEnabled: !magellanOptOut && (hasOnboardingStatusLicense || hasTvmBasicLicense),
		hasMdeLicenseWorkloads,
		isMachineValueEnabled,
		isCAPExperiencesEnabled,
		isSetCriticalityLevelEnabled,
		isAutomatedInvestigateEnabled,
		isExposureScoreEnabled,
		withUncategorizedTab,
		...
	};
};

Tools

  • Linters - restrict lines number and complexity (file / function level)
  • tsconfig.json - strictNullChecks, strictPropertyInitialization
  • IDE extensions like CodeMetrics and many more
  • Plato
  • AI tools 😀

summary

  • Cyclomatic complexity metric
  • Design solutions
  • Automatic tools

Thanks

🙏

Code Simplicity

By Shai Boharon

Code Simplicity

Code complexity metric and how to reduce it

  • 23