Refactor code with Clang Format

Mở đầu

Như chúng ta đã biết, phần lớn việc tiếp xúc với code là để đọc hiểu. Do vậy, việc viết code như thế nào là rất quan trọng. Code không chỉ để chương trình chạy nhanh, chạy tốt, mà còn phải đảm bảo việc người đến sau có thể dễ dàng hiểu được code, tiết kiệm thời gian và công sức khi tiếp nhận dự án. Chính vì thế, trong các dự án, code convention đã dần dần trở thành điều bắt buộc để đảm bảo việc maintain cũng như phát triển code được thực hiện dễ dàng hơn.

Tuy vậy, không phải lúc nào code cũng do chúng ta code từ đầu. Với những dự án outsource thì việc phải code trên project có sẵn của khách hàng là điều thường xuyên. Việc refactor code lại theo chuẩn của công ty sẽ mất rất nhiều thời gian và công sức . Do vậy, hôm nay tôi sẽ giới thiệu cho các bạn một công cụ giúp chúng ta có thể hoàn thành việc đó một cách tự đông.

I. Giới thiệu Clang-Format cho Xcode

ClangFormat-Xcode Là một Xcode-plugin giúp cho việc reformat code của bạn có thể thực hiện một cách tự động, được phát triển bởi @travisjeffery

1. Cài đặt

1.1 Cài đặt qua source code của Clang-Format

  • Uninstall
rm -r "~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/ClangFormat.xcplugin"

1.2 Cài đặt qua Alcatraz

Việc sử dụng Alcatraz sẽ giúp chúng ta dễ dàng tìm kiếm các plugin phù hợp cũng như quản lý nó một cách dễ dàng. Đơn giản bạn chỉ cần search tên plugin và bấm install.

Xcode > Windows > Package Manager (⌘⇧9) -> Search -> Install

Screen Shot 2016-01-08 at 10.04.49 AM.png

Screen Shot 2016-01-08 at 10.11.13 AM.png

Restart Xcode, khi chạy, Xcode sẽ hỏi xem bạn có muốn load bundle không, chọn Load Bundle

Screen Shot 2016-01-11 at 9.23.25 AM.png

II. Refactor code với Clang-Format

1. Sử dụng Clang-Format

Với Clang-Format chúng ta có thể format 1 đoạn text, 1 file hoặc 1 list file tùy thuộc vào nhu cầu của chúng ta trong việc refactor code.

Để sử dụng chúng tiện lợi hơn, bạn có thể cài đặt short cut cho các menu này để tiện sử dụng

System Preferences > Keyboard > Shortcuts > App Shortcuts > Click +
Application : Xcode
Menu title : Tên chính xác của Menu, ví dụ : "Format File in Focus"

"Screen Shot 2016-01-22 at 11.06.14 AM.png"

Clang Format đã cung cấp sẵn cho chúng ta 5 styles code là LLVM, Google, Chromium, Mozilla và WebKit

Đơn giản bạn chỉ cần Edit > Clang Format > lựa chọn 1 trong 5 styles đó -> Format code -> Done

Việc sử dụng Clang-Format với sự support tận tình như vậy là quá dễ dàng. Tuy vậy, với mỗi công ty, hay thậm chí với các dự án khác nhau, format code được tùy biến đi rất nhiều nên không phải 5 styles này, mà chính là styles custom của bạn mới là thứ chúng ta quan tâm nhất.

2. Custom Clang-Format styles

Khi bạn chọn Edit > Clang Format > File, Clang-Format sẽ tự động tìm kiếm file .clang-format trong folder gần file mà bạn đang làm việc nhất. Do vậy, thông thường, chúng ta sẽ đặt file .clang-format ở thư mục root của project (workspace).

Tuy vậy, trong hệ điều hành Mac, các file có tên với dấu . ở trước sẽ bị xem như là một file hệ thống và bị ẩn. Nếu không muốn như vậy, bạn có thể sử dụng tên file là _clang-format để thay thế

2.1 Cấu trúc file .clang-format

.clang-format file sử dụng YAML format

#comment.
key1: value1
key2: value2

Để tham khảo tài liệu về một file .clang-format đầy đủ option bạn có thể xem ở đây

2.2 Custom .clang-format file

Việc cấu hình 1 file .clang-format bao gồm rất nhiều options nên tôi chỉ trình bày qua một số trường quan trọng, và chỉ trong phạm vi ngôn ngữ Objective-C nhé

  • Language: Cpp

dòng này là bắt buộc để Clang-Format nhận diện ngôn ngữ Objective-C

  • AllowShortFunctionsOnASingleLine : bool
  • AllowShortIfStatementsOnASingleLine : bool
  • AllowShortLoopsOnASingleLine : bool

Các dòng này để xác định việc có cho phép ghép dòng code ngay trên cùng 1 dòng không

  • BreakBeforeBraces

dòng này sẽ cho chúng ta cài đặt kiểu break trước dấu { vốn là cái mà chúng ta sử dụng rất nhiều trong objective C khi sử dụng các hàm if/else/switch ...

  • TabWidth: integer
  • UseTab: Never

2 dòng này thường không có tác dụng vì Xcode sẽ nhận setting phần "Indentation" thay cho 2 dòng này

  • IndentWidth : integer
  • ContinuationIndentWidth : integer

Xác định chiều rộng của indent

  • ColumnLimit : integer

Nếu dòng lệnh vượt quá giá trị của dòng này, nó sẽ được break line tự động

  • ObjCSpaceAfterProperty : bool

nếu bằng true chúng ta sẽ có kết quả @property (nonatomic) thay vì @property(nonatomic)

  • ObjCSpaceBeforeProtocolList : bool

nếu bằng true chúng ta sẽ có Class <Protocol> thay cho Class<Protocol>

3.Một số vấn đề

Sử dụng Clang Format để refactor code là rất tuyệt, tuy vậy, nó vẫn còn 1 số vấn đề khiến chúng ta cảm thấy phiền phức

1. Vấn đề về việc tự động xuống dòng theo dấu :

Có một điều rất hay gặp khi code objective C là khi bạn xuống dòng trong 1 hàm, Apple sẽ hỗ trợ tự động cho bạn việc căn chỉnh các dòng theo dấu : như sau

           [[self alloc] initWithCode:nil
                                 name:@"すべての駅を選択"
                            checkable:YES
                           expandable:NO
                             dataType:PassDataTypeCellCheckAllData];

Đối với 1 số người, việc hỗ trợ này lại là điều làm họ cảm thấy khó chịu . Một hàm objective C thường khá dài do đó tạo cảm giác bị hụt ra phía sau khi đọc code

[tableView dequeueReusableCellWithIdentifier:@"Cell Identifier"
                                forIndexPath:indexPath];

Tuy vậy, Clang Format lại fix cứng tính năng này nên chúng ta không thể tìm thấy việc custom nó ở đâu cả

Giải pháp ư, có đây nhưng có vẻ hơi rắc rối đấy

2. Clang Format Swift

Rõ ràng, việc sử dụng Swift đang ngày một trở nên phổ biến, và Clang Format lại không nhận ra điều này .

Để hỗ trợ việc này chúng ta có thể sử dụng Swift Format để thay thế, tuy nhiên việc sử dụng nó cũng khá là bất tiện vì phải chạy trên terminal và format của nó đã bị fix cứng trong file format.py

Kết

Trên đây, tôi đã giới thiệu một công cụ giúp việc refactor code trở nên dễ dàng hơn . Tuy trong phạm vi bài viết chỉ nêu các cách cài đặt cũng như cấu hình cho Objective C nhưng Clang Format hoàn toàn có thể dùng để hỗ trợ việc refactor cho các ngôn ngữ khác như Java, C++. Tuy rằng Clang Format còn một vài hạn chế nhưng tôi tin rằng với sự tùy biến mà nó mang lại, việc refactor code sẽ trở nên dễ dàng và thuận lợi hơn rất nhiều