Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Refactoring Techniques Applied #183

Open
dquishpe opened this issue Aug 11, 2024 · 1 comment
Open

Code Refactoring Techniques Applied #183

dquishpe opened this issue Aug 11, 2024 · 1 comment

Comments

@dquishpe
Copy link

dquishpe commented Aug 11, 2024

This issue outlines several refactoring techniques applied to different methods in the code. Each technique aims to improve code readability, maintainability, and robustness.

  1. Decompose Conditional
    Problem: The method isSuitableForVm has a complex conditional expression in its return statement, making the code hard to understand and maintain.

Refactoring: The conditional expression is broken down into individual methods with descriptive names, making it easier to understand and maintain.
Original:

public boolean isSuitableForVm(Vm vm) {
    return (getVmScheduler().getPeCapacity() >= vm.getCurrentRequestedMaxMips()
            && getVmScheduler().getAvailableMips() >= vm.getCurrentRequestedTotalMips()
            && getRamProvisioner().isSuitableForVm(vm, vm.getCurrentRequestedRam()) 
            && getBwProvisioner().isSuitableForVm(vm, vm.getCurrentRequestedBw()));
}

Refactored Code:

public boolean isSuitableForVm(Vm vm) {
    return hasSufficientPeCapacity(vm) 
            && hasSufficientAvailableMips(vm) 
            && isRamSuitable(vm) 
            && isBwSuitable(vm);
}

private boolean hasSufficientPeCapacity(Vm vm) {
    return getVmScheduler().getPeCapacity() >= vm.getCurrentRequestedMaxMips();
}

private boolean hasSufficientAvailableMips(Vm vm) {
    return getVmScheduler().getAvailableMips() >= vm.getCurrentRequestedTotalMips();
}

private boolean isRamSuitable(Vm vm) {
    return getRamProvisioner().isSuitableForVm(vm, vm.getCurrentRequestedRam());
}

private boolean isBwSuitable(Vm vm) {
    return getBwProvisioner().isSuitableForVm(vm, vm.getCurrentRequestedBw());
}
  1. Parameterize Method
    Problem: The methods vmDeallocate and vmDeallocateAll perform similar actions with only differences in their internal operations.

Refactoring: The methods are combined using a parameter that specifies the operation to be performed.

Original Code:

protected void vmDeallocate(Vm vm) {
    getRamProvisioner().deallocateRamForVm(vm);
    getBwProvisioner().deallocateBwForVm(vm);
    getVmScheduler().deallocatePesForVm(vm);
    setStorage(getStorage() + vm.getSize());
}

protected void vmDeallocateAll() {
    getRamProvisioner().deallocateRamForAllVms();
    getBwProvisioner().deallocateBwForAllVms();
    getVmScheduler().deallocatePesForAllVms();
}

Refactored Code

protected void vmDeallocate(Vm vm) {
    getRamProvisioner().deallocateRamForVm(vm);
    getBwProvisioner().deallocateBwForVm(vm);
    getVmScheduler().deallocatePesForVm(vm);
    setStorage(getStorage() + vm.getSize());
}

protected void vmDeallocateAll() {
    getRamProvisioner().deallocateRamForAllVms();
    getBwProvisioner().deallocateBwForAllVms();
    getVmScheduler().deallocatePesForAllVms();
}
  1. Replace Conditional with Polymorphism
    Problem: The method processEvent uses a switch statement with multiple cases to handle different event types.

Refactoring: Subclasses are created to represent different types of events and a general interface is used. The shared method is moved to the corresponding subclasses.

Original Code:

public void processEvent(SimEvent ev) {
    int srcId = -1;

    switch (ev.getTag()) {
        case CloudSimTags.RESOURCE_CHARACTERISTICS:
            srcId = (Integer) ev.getData();
            sendNow(srcId, ev.getTag(), getCharacteristics());
            break;

        // other cases

        default:
            processOtherEvent(ev);
            break;
    }
}

Refactored Code:

public interface EventProcessor {
    void process(SimEvent ev);
}

public class ResourceCharacteristicsProcessor implements EventProcessor {
    @Override
    public void process(SimEvent ev) {
        int srcId = (Integer) ev.getData();
        sendNow(srcId, ev.getTag(), getCharacteristics());
    }
}

// Other EventProcessor implementations

public void processEvent(SimEvent ev) {
    EventProcessor processor = EventProcessorFactory.getProcessor(ev.getTag());
    if (processor != null) {
        processor.process(ev);
    } else {
        processOtherEvent(ev);
    }
}
  1. Extract Variable
    Problem: The method getNumHop contains a complex expression that may be difficult to understand.

Refactoring: Intermediate variables are introduced to make the code clearer.

Original Code:

public int getNumHop() {
    int PAIR = 2;
    return ((hopsNumber - PAIR) + 1) / PAIR;
}

Refactored Code:

public int getNumHop() {
    int pair = 2;
    int adjustedHopsNumber = hopsNumber - pair;
    return (adjustedHopsNumber + 1) / pair;
}
  1. Replace Error Code with Exception
    Problem: The method isFileValid handles invalid file cases with warnings instead of throwing exceptions.

Refactoring: Exceptions are used to handle invalid file cases, making error handling more explicit.

Original Code:

private boolean isFileValid(File file, String methodName) {
    if (file == null) {
        Log.printConcatLine(name, ".", methodName, ": Warning - the given file is null.");
        return false;
    }

    String fileName = file.getName();
    if (fileName == null || fileName.length() == 0) {
        Log.printConcatLine(name, "." + methodName, ": Warning - invalid file name.");
        return false;
    }

    return true;
}

Refactored Code:

private void validateFile(File file, String methodName) {
    if (file == null) {
        throw new InvalidFileException(name + "." + methodName + ": The given file is null.");
    }

    String fileName = file.getName();
    if (fileName == null || fileName.length() == 0) {
        throw new InvalidFileException(name + "." + methodName + ": Invalid file name.");
    }
}

@deRemo
Copy link
Member

deRemo commented Aug 27, 2024

Hi, @dquishpe, feel free to open a PR regarding your proposal so that we may discuss it (however, make sure you rebase your changes on the new cloudsim7g; You will have to update some method names, check the paper here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants