Tái cấu trúc một phương thức 1500 LỘC chỉ xây dựng giao diện người dùng đồ họa [đã đóng]


8

Tôi hiện đang suy nghĩ về cách cấu trúc lại một phương thức mà về cơ bản chỉ xây dựng giao diện người dùng.

Phương thức này dài hơn 1500 dòng mã (LỘC) - và đang đếm. Nó đã phát triển, không có kế hoạch làm thế nào để tiếp cận điều này. Bạn có thể thấy điều này quen thuộc.

Dù sao, về cơ bản, đây chỉ là một phương pháp lớn có một chút gì đó như thế này:

    .
    .
    .

    # null checks
    null_checks_bx = Box(True)

    null_checks_ck = CheckBox()
    null_checks_ck.set_text('Null checks throwing exceptions of type:')

    if 'doNullChecks' in options:
        null_checks_ck.set_active(options['doNullChecks'])
    else:
        null_checks_ck.set_active(True)

    # dict to sorted list: extract values from dict by list comprehension
    exceptions = sorted([exception.get_full_name() for exception in JavaTypes.exception_types])

    null_checks_se = Selector()
    null_checks_se.add_items(exceptions)
    null_checks_se.set_enabled(null_checks_ck.get_active())

    if 'nullChecksExceptionFullClassName' in options:
        null_checks_se.set_value(options['nullChecksExceptionFullClassName'])
    else:
        # default to first entry
        #(defaulting to doEquals = True and doHashCode = True by using hardcoded Commons Lang implies availability of Commons Lang NullArgumentException)
        null_checks_se.set_value(JavaTypes.exception_types[0].get_full_name())

    # callback
    Callbacks.sync_model_active_status(null_checks_ck, null_checks_se)

    null_checks_ck.add_clicked_callback(lambda: Callbacks.sync_model_active_status(null_checks_ck, null_checks_se))

    null_checks_bx.add(Label(indent), False, True)  # dummy indent label
    null_checks_bx.add(null_checks_ck, False, True)
    null_checks_bx.add(null_checks_se, False, True)

    # relationship entity class constructor calls
    relationship_constructor_calls_bx = Box(True)
    #relationship_constructor_calls_bx.set_spacing(5)
    #relationship_constructor_calls_bx.set_padding(3)

    relationship_constructor_calls_ck = CheckBox()
    relationship_constructor_calls_ck.set_text('Instantiate relationship entities (if all necessary columns present)')

    if 'doRelationshipConCalls' in options:
        relationship_constructor_calls_ck.set_active(options['doRelationshipConCalls'])
    else:
        relationship_constructor_calls_ck.set_active(False)

    relationship_constructor_calls_bx.add(Label(indent), False, True)  # dummy indent label
    relationship_constructor_calls_bx.add(relationship_constructor_calls_ck, False, True)

    # relationship not-null checks: this is an option independent of the null checks!
    relationship_not_null_checks = Box(True)
    #relationship_not_null_checks.set_spacing(5)
    #relationship_not_null_checks.set_padding(3)

    relationship_not_null_checks_ck = CheckBox()
    relationship_not_null_checks_ck.set_text('Not-null checks before relationship instantiation')

    relationship_not_null_checks_ck.set_enabled(relationship_constructor_calls_ck.get_active() and not null_checks_ck.get_active())

    if 'doRelationshipNotNullChecks' in options:
        relationship_not_null_checks_ck.set_active(options['doRelationshipNotNullChecks'])
    else:
        relationship_not_null_checks_ck.set_active(True)

    # callback
    Callbacks.sync_convenience_constructor_options(null_checks_ck, relationship_constructor_calls_ck, relationship_not_null_checks_ck)

    null_checks_ck.add_clicked_callback(lambda: Callbacks.sync_convenience_constructor_options(null_checks_ck, relationship_constructor_calls_ck, relationship_not_null_checks_ck))
    relationship_constructor_calls_ck.add_clicked_callback(lambda: Callbacks.sync_convenience_constructor_options(null_checks_ck, relationship_constructor_calls_ck, relationship_not_null_checks_ck))

    relationship_not_null_checks.add(Label(indent), False, True)  # dummy indent label
    relationship_not_null_checks.add(Label(indent), False, True)  # dummy indent label
    relationship_not_null_checks.add(relationship_not_null_checks_ck, False, True)

    # build final box
    checks_bx = Box(False)
    checks_bx.set_spacing(5)
    #checks_bx.set_padding(3)
    checks_bx.set_homogeneous(True)
    checks_bx.add(omit_auto_increment_columns_bx, False, True)
    checks_bx.add(omit_auto_timestamp_columns_bx, False, True)
    checks_bx.add(null_checks_bx, False, True)
    checks_bx.add(relationship_constructor_calls_bx, False, True)
    checks_bx.add(relationship_not_null_checks, False, True)

    # callback
    Callbacks.sync_model_active_status(convenience_constructors_ck, checks_bx)

    convenience_constructors_ck.add_clicked_callback(lambda: Callbacks.sync_model_active_status(convenience_constructors_ck, checks_bx))

    # need wrapped box for Panel class
    constructors_bx = Box(False)
    constructors_bx.set_spacing(5)
    constructors_bx.set_padding(3)
    #constructors_bx.set_homogeneous(True)
    constructors_bx.add(convenience_constructors_bx, False, True)
    constructors_bx.add(checks_bx, False, True)

    constructors_pn = Panel(TitledGroupPanel)
    constructors_pn.set_title('Constructors')
    constructors_pn.add(constructors_bx)

    # getters and setters
    is_conversion_bx = Box(True)
    #is_conversion_bx.set_spacing(3)
    #is_conversion_bx.set_padding(3)

    is_conversion_ck = CheckBox()
    is_conversion_ck.set_text('Convert respective column names starting with "is_"')
    is_conversion_ck.set_tooltip("Column is_incognito => getter isIncognito() (not getIsIncognito()) and setter setIncognito()")

    if 'doIsConversion' in options:
        is_conversion_ck.set_active(options['doIsConversion'])
    else:
        is_conversion_ck.set_active(True)

    is_conversion_bx.add(is_conversion_ck, False, True)

    # generate code for relationship getters and setters to synchronize with column fields
    sync_relationship_pk_fields_bx = Box(True)
    #sync_relationship_pk_fields_bx.set_spacing(3)
    #sync_relationship_pk_fields_bx.set_padding(3)

    sync_relationship_pk_fields = CheckBox()

    .
    .
    .

Bạn sẽ có được điểm.

Những gì tôi không thấy là các tiêu chí có thể là gì để phân tách phương thức này để mã sẽ trở nên dễ quản lý hơn, dễ hiểu hơn, v.v.

Các thực hành tốt nhất ở đây là gì?

Tôi có thể tạo một số phương pháp để tạo các loại bảng và widget định kỳ, nhưng điều này sẽ trở thành một nỗ lực khá tẻ nhạt cho những gì tôi không thấy được lợi ích thực sự.

Một lần nữa, một số cách tiếp cận thực tế, hữu ích đối với các phương pháp lớn, vụng về chỉ xây dựng giao diện người dùng đồ họa là gì?

Cảm ơn

PS: oh và BTW UI là một Hộp thoại trong một ứng dụng tiêu chuẩn, có cửa sổ (không có web) và hộp thoại này có 6 tab chứa hầu hết các hộp kiểm, nút radio và hộp văn bản. Nó là một plugin tạo mã mà người dùng có thể chọn rất nhiều tùy chọn. Tôi có thể đăng một hình ảnh ngay sau khi plugin chạy lại ...


Một điều tôi muốn thay đổi là tách thiết lập tĩnh khỏi trạng thái động.
CodeInChaos

@Kawu bạn cũng có thể chấp nhận câu trả lời nếu nó giải quyết vấn đề của bạn và trả lời câu hỏi một cách toàn diện.
toniedzwiedz

Tất nhiên rồi. Tôi không phải là người mới bắt đầu SO. Chỉ là khó mà vượt qua câu trả lời được chấp nhận.
Kawu

Câu trả lời:


27

Mã của bạn dường như có một tính năng bạn có thể sử dụng để lợi thế của bạn ở đây: tất cả những ý kiến ​​nhóm. Bạn có thể sử dụng những nhận xét đó làm cơ sở để chia phương thức thành các phần bằng cách trích xuất các phương thức nhỏ hơn . Bạn kéo từng đoạn vào phương thức riêng của mình, sau đó gọi phương thức đó từ vị trí ban đầu của mã.

Khi bạn bắt đầu rút những mảnh này ra, bạn sẽ tự nhiên tìm thấy sự trùng lặp hoặc bạn sẽ tự nhiên tìm thấy mối quan hệ mạnh mẽ giữa một số phương pháp. Khi bạn tìm thấy sự trùng lặp, bạn trích xuất nó thành các phương thức của trình trợ giúp để loại bỏ mã của bạn. Khi bạn tìm thấy ranh giới mối quan hệ tự nhiên, bạn có thể chia chúng thành các lớp riêng biệt có chức năng liên quan chặt chẽ hơn.

Dưới đây, ví dụ, tôi đã bắt đầu rút ra logic để xây dựng phần kiểm tra null. Tôi đã trích xuất nó như một phương thức, chia ra một vài phần cần một tên tốt hơn và bỏ tên tất cả các biến trong phương thức. Có rất nhiều điều có thể được thực hiện, nhưng đó là một bài tập cho người đọc.

def add_indent_label(self, box):
    box.add(Label(indent), False, True)

def get_null_checks(self, options):
    box = Box(True)

    checkbox = CheckBox()
    checkbox.set_text('Null checks throwing exceptions of type:')

    if 'doNullChecks' in options:
        checkbox.set_active(options['doNullChecks'])
    else:
        checkbox.set_active(True)

    exceptions = self.get_exceptions()

    selector = Selector()
    selector.add_items(exceptions)
    selector.set_enabled(checkbox.get_active())

    if 'nullChecksExceptionFullClassName' in options:
        selector.set_value(options['nullChecksExceptionFullClassName'])
    else:
        selector.set_value(self.get_first_exception())

    # callback
    Callbacks.sync_model_active_status(checkbox, selector)
    checkbox.add_clicked_callback(lambda: Callbacks.sync_model_active_status(checkbox, selector))

    self.add_indent_label(box);
    box.add(checkbox, False, True)
    box.add(selector, False, True)

    return box

def get_exceptions(self):
    return sorted([exception.get_full_name() for exception in JavaTypes.exception_types])

# This could probably have a better name
def get_first_exception(self):
    #(defaulting to doEquals = True and doHashCode = True by using hardcoded Commons Lang implies availability of Commons Lang NullArgumentException)
    return JavaTypes.exception_types[0].get_full_name()

Và trong mã gốc của bạn, nó trở thành:

null_checks_bx = self.get_null_checks(options)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.