การปรับโครงสร้าง Objective-C รุ่นเก่า
ประยุกต์ใช้เทคนิคการปรับโครงสร้างขั้นสูงเพื่อปรับปรุงการออกแบบ ความอ่านง่าย และความสามารถในการบำรุงรักษาโค้ด Objective-C ที่มีอยู่
การปรับโครงสร้าง Objective-C รุ่นเก่า เป็นบทเรียน Objective-C iOS Development for Legacy & Enterprise Apps ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Objective-C iOS Development for Legacy & Enterprise Apps และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Objective-C iOS Development for Legacy & Enterprise Apps มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Why Refactor Legacy Objective-C?
Welcome! In this lesson, we'll dive into refactoring legacy Objective-C codebases. Refactoring means improving the internal structure of code without changing its external behavior.
For older Objective-C apps, refactoring is crucial. It helps reduce bugs, makes the code easier to understand, and paves the way for new features and modernization.
Spotting Code Smells
Before we refactor, we need to identify areas that need improvement. These are often called 'code smells' – indicators that something might be wrong with the code's design.
- Long Methods: Methods that do too many things.
- God Objects: Classes that have too many responsibilities.
- Duplicated Code: The same logic appearing in multiple places.
- Poor Naming: Unclear variable, method, or class names.
Recognizing these helps you target your refactoring efforts.
Refactor: Extract Method
The Extract Method technique involves turning a code fragment from a larger method into its own new method. This makes the original method shorter and clearer, and the new method can be reused.
Consider this example where a single method handles multiple report generation steps:
#import <Foundation/Foundation.h>
@interface ReportGenerator : NSObject
- (void)generateDetailedReportForData:(NSArray<NSNumber *> *)data values:(NSArray<NSNumber *> *)values;
@end
@implementation ReportGenerator
- (void)generateDetailedReportForData:(NSArray<NSNumber *> *)data values:(NSArray<NSNumber *> *)values {
// Calculate sum of data
double sumData = 0;
for (NSNumber *num in data) {
sumData += [num doubleValue];
}
NSLog(@"Data Sum: %.2f", sumData);
// Calculate average of values
double sumValues = 0;
for (NSNumber *num in values) {
sumValues += [num doubleValue];
}
double avgValues = sumValues / [values count];
NSLog(@"Values Average: %.2f", avgValues);
// Check for anomalies (simplified example)
if (sumData > 100 && avgValues < 10) {
NSLog(@"Anomaly Detected.");
} else {
NSLog(@"No anomaly detected.");
}
// Log final report generation time
NSDate *now = [NSDate date];
NSLog(@"Report generated at: %@", now);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
ReportGenerator *generator = [[ReportGenerator alloc] init];
NSArray<NSNumber *> *sampleData = @[@20.0, @30.0, @60.0];
NSArray<NSNumber *> *sampleValues = @[@5.0, @8.0, @7.0];
[generator generateDetailedReportForData:sampleData values:sampleValues];
}
return 0;
}Refactor: Explaining Variable
Sometimes, complex expressions can be hard to understand at a glance. The Introduce Explaining Variable refactoring creates a temporary variable to hold the result of a complex expression, giving it a clear, descriptive name.
This improves readability without changing the logic. Look at this conditional:
#import <Foundation/Foundation.h>
@interface PriceCalculator : NSObject
- (CGFloat)calculatePriceForQuantity:(NSInteger)quantity isPremiumCustomer:(BOOL)isPremium hasCoupon:(BOOL)hasCoupon;
@end
@implementation PriceCalculator
- (CGFloat)calculatePriceForQuantity:(NSInteger)quantity isPremiumCustomer:(BOOL)isPremium hasCoupon:(BOOL)hasCoupon {
CGFloat basePrice = 100.0 * quantity;
// Complex condition
if (quantity > 10 && isPremium && !hasCoupon) {
basePrice *= 0.8; // 20% discount
} else if (quantity > 5 && (isPremium || hasCoupon)) {
basePrice *= 0.9; // 10% discount
}
return basePrice;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
PriceCalculator *calculator = [[PriceCalculator alloc] init];
NSLog(@"Price 1: %.2f", [calculator calculatePriceForQuantity:15 isPremiumCustomer:YES hasCoupon:NO]);
NSLog(@"Price 2: %.2f", [calculator calculatePriceForQuantity:7 isPremiumCustomer:NO hasCoupon:YES]);
}
return 0;
}Refactor: Symbolic Constants
Replace Magic Number with Symbolic Constant helps make code more understandable. A 'magic number' is a hard-coded numerical value that appears directly in the code without explanation.
Replacing these with named constants (e.g., #define or const) improves readability and makes future changes easier.
#import <Foundation/Foundation.h>
@interface ScoreEvaluator : NSObject
- (NSString *)evaluateScore:(NSInteger)score;
@end
@implementation ScoreEvaluator
- (NSString *)evaluateScore:(NSInteger)score {
// Magic numbers: 90, 75, 60
if (score >= 90) {
return @"Excellent";
} else if (score >= 75) {
return @"Good";
} else if (score >= 60) {
return @"Pass";
} else {
return @"Fail";
}
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
ScoreEvaluator *evaluator = [[ScoreEvaluator alloc] init];
NSLog(@"Score 95: %@", [evaluator evaluateScore:95]);
NSLog(@"Score 70: %@", [evaluator evaluateScore:70]);
}
return 0;
}Refactor: Consolidate Conditionals
When several conditional expressions lead to the same result, you can Consolidate Conditional Expression. This means combining them into a single, more concise logical expression.
It simplifies the code and reduces redundancy, making it easier to read and maintain.
#import <Foundation/Foundation.h>
@interface UserValidator : NSObject
- (BOOL)isUserEligibleForFeature:(BOOL)hasSubscription isActive:(BOOL)isActive isBetaTester:(BOOL)isBetaTester;
@end
@implementation UserValidator
- (BOOL)isUserEligibleForFeature:(BOOL)hasSubscription isActive:(BOOL)isActive isBetaTester:(BOOL)isBetaTester {
// Original logic:
if (hasSubscription) {
return YES;
}
if (isActive && isBetaTester) {
return YES;
}
return NO;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
UserValidator *validator = [[UserValidator alloc] init];
NSLog(@"User 1 Eligible: %@", [validator isUserEligibleForFeature:YES isActive:NO isBetaTester:NO] ? @"YES" : @"NO");
NSLog(@"User 2 Eligible: %@", [validator isUserEligibleForFeature:NO isActive:YES isBetaTester:YES] ? @"YES" : @"NO");
NSLog(@"User 3 Eligible: %@", [validator isUserEligibleForFeature:NO isActive:YES isBetaTester:NO] ? @"YES" : @"NO");
}
return 0;
}Refactor: Move Method/Field
The Move Method and Move Field refactorings are about improving class cohesion and reducing coupling. If a method or a field in one class primarily interacts with another class, it might belong in that other class instead.
- Move Method: Relocates a method to the class where it makes most sense.
- Move Field: Moves an instance variable to the class that uses it most.
This ensures that related data and behavior are kept together.
Refactor: Extract Class
When a single class grows too large and takes on too many responsibilities, it becomes a 'God Object'. The Extract Class refactoring helps break down such a class into smaller, more focused classes, each with a single responsibility.
This improves modularity, testability, and makes the code easier to manage.
#import <Foundation/Foundation.h>
// Before (simplified God Object concept)
@interface UserProfileManager : NSObject
@property (nonatomic, strong) NSString *username;
@property (nonatomic, strong) NSString *email;
- (void)loadUserDataFromRemoteServer;
- (void)saveUserDataToLocalCache;
- (void)displayProfileOnScreen;
- (BOOL)authenticateUserWithPassword:(NSString *)password;
@end
@implementation UserProfileManager
- (void)loadUserDataFromRemoteServer { NSLog(@"Loading user data..."); }
- (void)saveUserDataToLocalCache { NSLog(@"Saving user data..."); }
- (void)displayProfileOnScreen { NSLog(@"Displaying profile..."); }
- (BOOL)authenticateUserWithPassword:(NSString *)password {
NSLog(@"Authenticating user...");
return YES;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
UserProfileManager *manager = [[UserProfileManager alloc] init];
manager.username = @"coddykit";
[manager authenticateUserWithPassword:@"password"];
[manager loadUserDataFromRemoteServer];
[manager displayProfileOnScreen];
}
return 0;
}Readability: Naming & Style
Beyond structural changes, improving readability is a critical part of refactoring legacy code. This includes:
- Descriptive Naming: Use clear, concise names for classes, methods, and variables that reflect their purpose.
- Objective-C Conventions: Adhere to standard Objective-C naming conventions (e.g.,
camelCasefor variables, `CapitalizedCamelCase` for classes,- (void)doSomethingWith:(id)parameterfor methods). - Consistent Formatting: Maintain consistent indentation and code style throughout the codebase.
These practices make the code much easier for you and others to understand.
Refactoring Challenge
Refactoring helps us maintain and evolve complex applications.
Which refactoring technique best addresses a method that has grown too large and performs multiple unrelated tasks?
Lesson Recap
In this lesson, we explored key refactoring techniques for legacy Objective-C codebases:
- Identifying 'code smells' like long methods and God objects.
- Applying techniques such as Extract Method, Introduce Explaining Variable, and Replace Magic Number with Symbolic Constant.
- Improving structure with Consolidate Conditional Expression, Move Method/Field, and Extract Class.
- The importance of clear naming and consistent style.
Continuous refactoring is essential for keeping legacy apps maintainable and ready for future development!
คำถามที่พบบ่อย
บทเรียน “การปรับโครงสร้าง Objective-C รุ่นเก่า” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การปรับโครงสร้าง Objective-C รุ่นเก่า” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Objective-C iOS Development for Legacy & Enterprise Apps ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Objective-C iOS Development for Legacy & Enterprise Apps มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การปรับโครงสร้าง Objective-C รุ่นเก่า”
ประยุกต์ใช้เทคนิคการปรับโครงสร้างขั้นสูงเพื่อปรับปรุงการออกแบบ ความอ่านง่าย และความสามารถในการบำรุงรักษาโค้ด Objective-C ที่มีอยู่ คุณปฏิบัติ Objective-C iOS Development for Legacy & Enterprise Apps ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Objective-C iOS Development for Legacy & Enterprise Apps หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Objective-C iOS Development for Legacy & Enterprise Apps บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การปรับโครงสร้าง Objective-C รุ่นเก่า” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Objective-C iOS Development for Legacy & Enterprise Apps นี้ได้ไหม
ได้ บทเรียน Objective-C iOS Development for Legacy & Enterprise Apps ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การปรับโครงสร้าง Objective-C รุ่นเก่า
- การจัดการหนี้ทางเทคนิค
- แนวทางการบำรุงรักษาระยะยาว
- การเขียนการทดสอบลักษณะการทำงานก่อนปรับโครงสร้าง