1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình Wrox Professional Xcode 3 cho Mac OS part 24 docx

13 126 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 13
Dung lượng 4,67 MB

Nội dung

10 Refactoring WHAT'S IN THIS CHAPTER? Renaming classes, types, methods, functions, and variables Reorganizing code and restructuring classes Modernizing your code Despite our best efforts, class and data structures don ’ t always endure. New features, requirements, operating system evolution, and improvements elsewhere in your application may cause you to revisit the design of your existing class and data architecture. You may need to reorganize the hierarchy of your classes, migrate functionality from one class to another, take advantage of new language features, or simply rename a variable so that it more accurately refl ects its purpose. These kinds of changes are referred to as refactoring your code. Making structural changes to your code using the editor and the search and replace tools can often be tedious, time consuming, and error prone. In the days before refactoring, I would often rename or relocate an instance variable by simply changing its declaration, and then hunting down and correcting all of the compilation errors that resulted — not the most productive way to spend an afternoon. Fortunately, Xcode now provides a refactoring tool that helps you make many common structural changes to your application, quickly and succinctly. It uses the Code Sense database and an inherent knowledge of C and Objective - C syntax to intelligently rename symbols, reorganize classes, and streamline code. This chapter describes the kinds of changes the refactoring tool performs and the steps required. Refactoring is formally defi ned as a change to the internal structure of your program that doesn ’ t change its external, or functional, behavior. The reality is that any change, no matter how careful, can have unintended consequences. The section “ Refactoring Pitfalls ” discusses some of these potential problems, how to address them, and some best practices. ➤ ➤ ➤ c10.indd 185c10.indd 185 1/21/10 3:20:10 PM1/21/10 3:20:10 PM Download at getcoolebook.com 186 ❘ CHAPTER 10 REFACTORING REFACTORING WORKFLOW To refactor something in your project, follow these general steps: 1. Select the symbol or code fragment to refactor. 2. Choose the Edit ➪ Refactor (Shift+Command+J) command to open the refactoring tool window. 3. Select the type of refactoring to perform, provide whatever additional information is required, and choose options. 4. Preview the refactoring. 5. Commit the refactoring. The process begins by selecting the specifi c symbol name or code fragment in the editor that represents what you want to refactor. Once selected, choose the Edit ➪ Refactor command to present the refactoring tool window, as shown in Figure 10 - 1. FIGURE 10-1 The refactor tool determines which refactoring methods, called transformations , can be applied to the selected text. Select your desired transformation from the pop - up menu on the left, as shown in Figure 10 - 1. What transformations are available will depend entirely on the nature and context of the selection. Xcode offers to rename or create a superclass if a class name is selected. A selected block of code could be extracted or possibly modernized. c10.indd 186c10.indd 186 1/21/10 3:20:13 PM1/21/10 3:20:13 PM Download at getcoolebook.com Refactoring uses the Code Sense index. This means that Code Sense must be enabled, up - to - date, and it must be able to make sense of your code. As a general rule, don ’ t refactor code that won ’ t compile — especially code that contains syntax errors that might prevent Code Sense from interpreting its meaning. See Chapter 7 if you need to turn Code Sense on or reindex your project. Once the transformation is chosen, supply whatever additional information, if any, the transformation requires. For a rename transformation, you ’ ll need to supply the symbol ’ s new name. Other transformations might require several pieces of information. Some transformations present options, typically used to control what additional, non - code changes are made. For example, renaming a class presents two options: one will also rename KVC references to that class found in Interface Builder documents and Core Data models. The other option will automatically rename the source fi les that contain the class ’ s defi nition so that they continue to match the class name. After you ’ ve prepared the transformation, start the process by clicking the Preview button. The process scans your entire project and prepares a list of proposed changes. At this point no changes have actually been made. You can preview the changes using the differences browser, as shown in Figure 10 - 2. It may also present a list of warnings that should be considered. FIGURE 10-2 You can elect which of the changes you ’ re going to allow the refactoring tool to make using the check boxes next to each fi le in the list. Uncheck a fi le, and Xcode will not make any of the proposed changes contained therein. You also have the option of an added safety net, in the form of a project snapshot. Checking the Snapshot option makes a snapshot of your entire project before making any of the proposed changes. This also has the advantage of being able to selectively reverse unwanted changes on a change - by - change basis. See Chapter 11 for more about snapshots. Once you ’ ve defi ned and previewed the transformation, click the Apply button to commit the changes. When fi nished, the Refactor window closes and returns you to your (now modifi ed) project. Refactoring Workfl ow ❘ 187 c10.indd 187c10.indd 187 1/21/10 3:20:13 PM1/21/10 3:20:13 PM Download at getcoolebook.com 188 ❘ CHAPTER 10 REFACTORING C AND OBJECTIVE - C TRANSFORMATIONS As of this writing, the refactoring tool only refactors C and Objective - C source code; C++ and Java programmers are just out of luck. The next few sections describe the specifi c transformations that the refactoring tool provides, along with some examples. Rename The rename transformation is the simplest and most fl exible. It will rename any of the following: Global, instance, parameter, and automatic variable names Function names Typdef, structure tag, and enum names Class names Method signatures To rename a symbol, follow these steps: 1. Select a symbol name or at least one token of an Objective - C message name. 2. Choose the Edit ➪ Refactor command. 3. Select the Rename transformation. 4. Supply a replacement name and choose any additional option. All of the rename transformations occur within the symbol ’ s scope. For example, renaming an integer variable from c to i , as shown in Figure 10 - 3, only renames references that refer to the selected variable. Refactor is not confused by the unichar c variable, even though it is nested within the block of code where int c is declared. In this respect, refactoring is more intelligent than the Edit All in Scope command described in the “ Editing Symbol Names ” section of Chapter 7. Edit All in Scope only analyzes the textual context, and would have renamed both c variables to i . ➤ ➤ ➤ ➤ ➤ FIGURE 10-3 c10.indd 188c10.indd 188 1/21/10 3:20:19 PM1/21/10 3:20:19 PM Download at getcoolebook.com Renaming method signatures is particularly accurate and fl exible. For example, when renaming an Objective - C method name, Xcode picks up the entire method signature and asks that you supply a replacement. You can change any, or all, of the method name tokens and the refactoring tool will make the appropriate changes in the code. In the example shown in Figure 10 - 4, the method scheduleDate:time:room: is being renamed to scheduleStartingAt:duration:room: . The replacement method name must match the number and order of the original arguments. FIGURE 10-4 TIP TO REMEMBER T he refactoring tool can be used as an intelligent multi - fi le search for instance variables and method names. Select a variable or method and rename it to something else, and then preview — but don ’ t commit — the refactoring. In the preview, the rename transformation will fi nd all references to a variable, ignoring symbols with the same name in other contexts. Similarly, the rename transformation can quickly locate all instances of a complex Objective - C message name, even one that ’ s split across multiple lines. When renaming a class, you are given the additional option of renaming any source fi les with the same name. By tradition, the fi les that defi ne the Hue class are named Hue.h and Hue.m . Renaming the Hue class to Color would also rename the fi les to Color.h and Color.m , and update any #include “ Hue.h ” and #import “ Hue.m ” statements to match. The Rename Related KVC/Core Data Members option extends the refactoring beyond the scope of your source code. It scours NIB documents and Core Data models for any references to the class, method, or variable being remained. This option will update class inheritance, member names, outlet connections, actions, and bindings. If you have any NIB document or Core Data models that refer to your class, I highly recommend checking this option. C and Objective - C Transformations ❘ 189 c10.indd 189c10.indd 189 1/21/10 3:20:20 PM1/21/10 3:20:20 PM Download at getcoolebook.com 190 ❘ CHAPTER 10 REFACTORING Extract Reusable, modular code is the hallmark of effi cient programming. Often, however, code that could be organized into its own method or function is originally embedded in a larger function — often because you don ’ t realize its utility until later. Take the situation shown in Listing 10 - 1. Here, the programmer is writing a new rescheduleStartingAt:duration: method, when she realizes that the loop she is about to write is identical to the one in scheduleStartingAt:duration:inRoom: . LISTING 10 - 1: Repetitious code - (void)scheduleStartingAt:(NSDate*)date duration:(NSTimeInterval)minutes inRoom:(RoomIdentifier)roomID { start = date; duration = minutes*60.0; room = roomID; NSEnumerator *e = [participants objectEnumerator]; Person *participant; while ( (participant=[e nextObject])!=nil ) { [participant updateCalendarEvent:self]; } } - (void)rescheduleStartingAt:(NSDate*)date duration:(NSTimeInterval)minutes { start = date; duration = minutes*60.0; NSEnumerator *e = } Ideally, the loop that sends update events to all of the meeting participants should be isolated in its own method. Then, rescheduleStartingAt:duration: and scheduleStartingAt:duration: inRoom: can reuse the logic. This transformation is called an extraction. To extract a block of code, follow these steps: 1. Select the block of code you want to reuse. 2. Choose the Edit ➪ Refactor command. 3. Choose the Extract transformation. 4. Decide whether you want the code to extract into a C function or an Objective - C method. 5. Supply the name of the new function or method. Figure 10 - 5 illustrates our programmer exacting the enumeration loop in Listing 10 - 1 into its own method. The extract transformation lifts a local fragment of code and puts it into its own Objective - C method or C function (your choice). In the example shown in Figure 10 - 5, our programmer is extracting the c10.indd 190c10.indd 190 1/21/10 3:20:22 PM1/21/10 3:20:22 PM Download at getcoolebook.com enumeration loop into a new method named - (void)updateParticipants . The original code is replaced with a message that invokes the new method. After the extraction, the rescheduleStartingAt: duration: can now be completed with a single [self updateParticipants]; statement. FIGURE 10-5 T he formatting of extracted code can be a bit erratic. After extraction, select the new method and reformat it by typing Control+I. When extracting code, Xcode analyzes the scope of all of the variable references within the code block. Any variable that isn ’ t in scope when the code is relocated to its own method (or function) is converted into a parameter. In the previous example, both the participants and self instance variables are still accessible in the new updateParticipants method. If you choose to extract this code into a C function, or the loop refers to any automatic variables declared earlier in the method, those references will be converted into parameters, as shown in Figure 10 - 6. C and Objective - C Transformations ❘ 191 c10.indd 191c10.indd 191 1/21/10 3:20:23 PM1/21/10 3:20:23 PM Download at getcoolebook.com 192 ❘ CHAPTER 10 REFACTORING The function notify_participants( ) in Figure 10 - 6 has no object context, so the collection of participants and the receiving object were converted to parameters. Encapsulate The encapsulate transformation creates getter and setter methods for class instance variables. Figure 10 - 7 shows the tasks variable being encapsulated. FIGURE 10-6 FIGURE 10-7 c10.indd 192c10.indd 192 1/21/10 3:20:34 PM1/21/10 3:20:34 PM Download at getcoolebook.com C and Objective - C Transformations ❘ 193 To encapsulate an instance variable, follow these steps: 1. Select the name of the instance variable. 2. Choose the Edit ➪ Refactor command. 3. Choose the Encapsulate transformation. 4. Optionally edit the getter and setter method names. Xcode generates a matched pair of KVC - compliant method names, but you can change them if you want. The encapsulate transformation generates a getter and setter method for the instance variable and then replaces any existing references to the variable with messages (that is, ivar with [object ivar] and ivar= with [object setIvar: ] ). As of this writing, a number of unfortunate limitations keep the encapsulate transformation from being truly useful, except in a narrow set of circumstances. For the specifi cs, see the “ Encapsulate ” portion of the “ Refactoring Pitfalls ” section, later in this chapter. Because of these issues, I recommend using the encapsulate transformation only when: You are not using Objective - C 2.0. You are using managed memory (not garbage collection). You have just added an instance variable and want to create getter and setter methods for it, but have not yet used the variable in any code. If you ’ ve already used the variable in your code, you will need to carefully review the memory management of the object afterwards. Your property does not need to be thread - safe. In any other circumstances, I ’ d recommend using Objective - C @property and @synthesize directives instead. See the “ Updating a Project to Objective - C 2.0 ” section later in this chapter. Create Superclass The create superclass transformation creates a new class defi nition and inserts it between an existing class and its original superclass. This is most useful when you need to create a more abstract superclass for an existing class whose functionality needs to be partitioned. To create a superclass, follow these steps: 1. Select the name of the existing class. 2. Choose the Edit ➪ Refactor command. 3. Choose the Create Superclass transformation. 4. Supply a new class name and choose whether the new class should be defi ned in the existing fi le or defi ned in a new set of source fi les with the same name. Xcode changes the inheritance of the existing class so that it is now a subclass of the new class, which is a subclass of the original superclass. If you asked Xcode to generate new class fi les, those fi les are added to the project and appropriate #import directives are inserted into the original fi les, as shown in Figure 10 - 8. ➤ ➤ ➤ ➤ c10.indd 193c10.indd 193 1/21/10 3:20:35 PM1/21/10 3:20:35 PM Download at getcoolebook.com 194 ❘ CHAPTER 10 REFACTORING In the hypothetical project management program, you decide that you need an intermediate class between the very abstract Event class and the very specifi c Meeting class. The create superclass transformation quickly defi nes a new ScheduledMeeting class, changes the superclass of the Meeting class, and then creates and adds all the necessary project fi les. Move Up and Move Down After applying a create superclass transformation, or simply creating a new subclass, you may want to migrate properties or functionality from a class to its superclass or vice versa. That ’ s what the move up and move down transformations do. To move an instance variable or method to a superclass or one of its subclasses, follow these steps: 1. Select the instance variable declaration or method name. 2. Choose the Edit ➪ Refactor command. 3. Choose either the Move Up or Move Down transformation. 4. Select the desired options: a. If moving an instance variable up, you may also elect to move related methods — any method that refers to the variable — to the superclass. b. If moving down, the Refactor tool presents a list of the immediate subclasses of the class; choose which subclasses will get a copy of the variable or method. Using the project management example again, the start and duration properties in the Meeting class need to be migrated to the new ScheduledEvent superclass, as shown in Figure 10 - 9. FIGURE 10-8 c10.indd 194c10.indd 194 1/21/10 3:20:36 PM1/21/10 3:20:36 PM Download at getcoolebook.com [...]... any statements before or after the loop, even if they include loop initialization 2 3 Choose the Edit ➪ Refactor command Choose the Modernize Loop transformation The process begins by selecting the entire for loop statement and block, as shown in Figure 10 -10 Download at getcoolebook.com c10.indd 195 1/21/10 3: 20 :37 PM 196 ❘ CHAPTER 10 REFACTORING FIGURE 10-10 Loop modernization only transforms for... 2.0, follow these steps: 1 2 Choose the Edit ➪ Convert to Objective- C 2.0 command Select either, or both, of the Modernize loops or Use properties transformations The modernize loops transformation is the same one described in the previous section, just applied globally to every Objective- C source fi le in your project Download at getcoolebook.com c10.indd 197 1/21/10 3: 20:41 PM ... NSEnumerator* e = [collection reverseObjectEnumerator]; for ( id obj in e ) { } The enumerator acts as a proxy for its collection The statement loops through the objects returned by the enumerator This is particularly useful with enumerators that return a subset of a collection or process objects in a different order, like -[NSDictionary keysSortedByValueUsingSelector:] It should be noted that this trick... does not improve the performance of your application; a fast enumeration using an enumerator object isn’t any faster than using the enumerator object directly In other words, you don’t get the “fast” part of fast enumeration; you just get the convenience of a concise syntax UPDATING A PROJECT TO OBJECTIVE- C 2.0 The Edit ➪ Convert to Objective- C 2.0 command is specifically designed to ease that transition... loop transformation updates a while loop, it replaces the traditional NSEnumerator pattern shown in Figure 10 -11 with its modern equivalent FIGURE 10-11 Download at getcoolebook.com c10.indd 196 1/21/10 3: 20:40 PM Updating a Project to Objective - C 2.0 ❘ 197 Loop modernization only transforms while loops that meet these criteria: ➤ The while loop iterates through the objects in a collection using an . the name of the existing class. 2. Choose the Edit ➪ Refactor command. 3. Choose the Create Superclass transformation. 4. Supply a new class name and choose whether the new class should be. of the instance variable. 2. Choose the Edit ➪ Refactor command. 3. Choose the Encapsulate transformation. 4. Optionally edit the getter and setter method names. Xcode generates a matched pair. code, follow these steps: 1. Select the block of code you want to reuse. 2. Choose the Edit ➪ Refactor command. 3. Choose the Extract transformation. 4. Decide whether you want the code to extract

Ngày đăng: 04/07/2014, 06:20

TỪ KHÓA LIÊN QUAN