Attualmente mi sto graffiando la testa su come refactoring un metodo che fondamentalmente costruisce solo l'interfaccia utente.
Il metodo è lungo più di 1500 righe di codice (LOC) e il conteggio. È cresciuto, non c'era un piano su come affrontarlo. potresti trovare questo familiare.
In ogni caso, è fondamentalmente solo un metodo di grandi dimensioni che va un po 'in questo modo:
.
.
.
# 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()
.
.
.
Ottieni il punto.
Quello che non vedo è quale potrebbe essere il criterio per dividere questo metodo in modo che il codice diventi più gestibile, più comprensibile ecc. pp.
Quali sono le migliori pratiche qui?
Potrei creare alcuni metodi che creerebbero tipi ricorrenti di pannelli e widget, ma questo diventerebbe uno sforzo piuttosto noioso per quello che non riesco a vedere il vero guadagno.
Ancora una volta, quali sono alcuni approcci pratici e utili a metodi ampi e goffi che costruiscono solo l'interfaccia grafica?
Grazie
PS: oh e BTW l'interfaccia utente è una singola finestra di dialogo in un'applicazione standard con finestre (senza web) e questa finestra di dialogo ha 6 schede che contengono principalmente caselle di controllo, pulsanti di opzione e caselle di testo. È un plug-in di generazione del codice che l'utente può scegliere da molte opzioni. Potrei pubblicare un'immagine non appena avrò riavviato il plug-in ...