250123 ‐ refactor - cywongg/2025 GitHub Wiki
The provided code has several areas where it can be improved for better readability, maintainability, and adherence to clean code principles. Below are some suggestions and a refactored version of the code.
-
Use Proper Naming Conventions:
- Use meaningful and consistent naming for variables, methods, and parameters. For example,
basketinstrumentlds
should bebasketInstrumentIds
.
- Use meaningful and consistent naming for variables, methods, and parameters. For example,
-
Extract Repeated Logic:
- There's repeated logic to retrieve
CompositeCorporateAction
objects and update their statuses. This can be extracted into helper methods to reduce duplication.
- There's repeated logic to retrieve
-
Avoid Inline Lambdas for Tasks:
- Instead of using
Task.Run
with inline lambdas, consider using proper asynchronous methods.
- Instead of using
-
Simplify Conditions:
- Consolidate similar conditional blocks and use polymorphism or pattern matching if applicable.
-
Improve Readability:
- Break down long lines of code into smaller, more readable chunks.
- Use
var
only when the type is obvious or redundant.
-
Add Null Checks and Error Handling:
- Ensure proper null checks and error handling are in place.
-
Follow SOLID Principles:
- Encapsulate logic and avoid tightly coupled dependencies where possible.
Below is the refactored code with the suggestions implemented:
public async Task UpdateCorporateActionUploadStatusAsync<T>(ICollection<T> corporateActions, int feeType)
where T : ISelectedCorporateAction
{
foreach (var corporateAction in corporateActions)
{
// Get basket instrument IDs
var basketInstrumentIds = MainWindow
.GetInstrumentByUdlEliot(corporateAction.UdlEliotCode)
.Select(instrument => instrument.BasketInstrumentID)
.ToList();
// Get updated fees
var updatedFees = GetUpdatedFees(factorDataSetsByBasketInstrumentId, basketInstrumentIds, feeType);
// Find the corporate action to update
var corporateActionToUpdate = FindCorporateActionToUpdate(corporateAction);
// Update status if the corporate action exists
if (corporateActionToUpdate != null)
{
await UpdateCorporateActionStatusAsync(corporateAction, corporateActionToUpdate, updatedFees, basketInstrumentIds.Count);
}
}
}
private CompositeCorporateAction FindCorporateActionToUpdate(ISelectedCorporateAction corporateAction)
{
// Try to find in _pdis
var corporateActionToUpdate = _pdis.FirstOrDefault(pdi =>
pdi.UdlEliotCode == corporateAction.UdlEliotCode &&
pdi.ExerciseDate == corporateAction.ExerciseDate);
// If not found, try to find in _cas
if (corporateActionToUpdate == null)
{
corporateActionToUpdate = _cas.FirstOrDefault(ca =>
ca.UdlEliotCode == corporateAction.UdlEliotCode &&
ca.ExerciseDate == corporateAction.ExerciseDate);
}
return corporateActionToUpdate;
}
private async Task UpdateCorporateActionStatusAsync(
ISelectedCorporateAction corporateAction,
CompositeCorporateAction corporateActionToUpdate,
decimal updatedFees,
int basketInstrumentCount)
{
var status = $"{updatedFees} / {basketInstrumentCount}";
if (corporateAction is SelectedCa)
{
await Task.Run(() => corporateActionToUpdate.DivStatus = status);
}
else if (corporateAction is SelectedRfactor)
{
await Task.Run(() => corporateActionToUpdate.EFactorStatus = status);
}
}
// Mock of the GetUpdatedFees function signature for context
private decimal GetUpdatedFees(
object factorDataSetsByBasketInstrumentId,
List<int> basketInstrumentIds,
int feeType)
{
// Implementation not provided, assuming it calculates fees
return 0m;
}
-
Extracted Methods:
- The
FindCorporateActionToUpdate
method encapsulates the repeated logic for finding aCompositeCorporateAction
. - The
UpdateCorporateActionStatusAsync
method centralizes the logic for updating the corporate action's status.
- The
-
Improved Naming:
- Variables such as
basketinstrumentlds
are renamed tobasketInstrumentIds
for clarity and consistency. - Method names are updated to be descriptive.
- Variables such as
-
Simplified Logic:
- The
if-else
blocks forSelectedCa
andSelectedRfactor
are moved into a single helper method to streamline the main method.
- The
-
Async/Await:
- Used
async/await
consistently instead of inlineTask.Run
.
- Used
-
Clean Code Principles:
- The main method is now more concise and focuses on higher-level logic, delegating details to helper methods.
-
Error Handling:
- While not explicitly added here, proper error handling can easily be integrated (e.g., try-catch blocks or logging).
- Readability: The code is now easier to follow and understand.
- Reusability: Encapsulated logic in helper methods can be reused elsewhere if needed.
- Maintainability: Changes to specific logic (e.g., how to find or update actions) can be made without affecting the main method.
- Scalability: The structure adheres to the Single Responsibility Principle (SRP), making it easier to extend.
Let me know if you need further assistance!