下面是回傳小部件的顫振函式的代碼片段。它根據四個不同的變數回傳一個按鈕或文本小部件。
Widget _renderReservationState() {
if (reservationsDetailState.isFinished == false) {
if (reservationsDetailState.rsvpStatus == "Attending") {
if (reservationsDetailState.attendanceStatus == "Attended") {
return Center(
child: Text("Registration completed");)
} else {
if (reservationsDetailState.isEditing == false) {
return SizedBox(
child: Button(
onPressed: () {
if (myReservationsDetailState.isEditing) {
_setEditMode(false);
} else {
_setEditMode(true);
}
},
title: "Edit reservation"),
width: double.infinity);
} else {
return SizedBox(
child: Button(
onPressed: () {
if (reservationsDetailState.isEditing) {
_confirmReservation(dateController.text,
timeController.text, attendeeController.text);
} else {
_setEditMode(true);
}
},
title: "Confirm reservation"),
width: double.infinity);
}
}
} else {
return SizedBox(
child: Button(
onPressed: () => {
_confirmReservation(dateController.text,
timeController.text, attendeeController.text),
},
title: "Make a reservation"),
width: double.infinity);
}
} else {
if (myReservationsDetailState.attendanceStatus == "Attended") {
return Center(
child: Text("Thank you for your visit")
);
} else {
return Center(
child: Text("Please join next time");)
}
}
}
現有代碼是幾百行的嵌套 if-else。我已經將它重構為更短,但我對這個實作也不滿意。任何建議或建議將不勝感激。
uj5u.com熱心網友回復:
關于提高可讀性的一些一般建議:
擺脫不必要的
if檢查:if (someCondition) { _setEditMode(false); } else { _setEditMode(true); }相當于:
_setEditMode(!someCondition);避免
if (condition == false)。如果condition不可為空,請使用if (!condition).盡可能將嵌套
if塊折疊成if-else if鏈:if (condition1) { ... } else { if (condition2) { ... } else { ... } }可以不縮進一個級別為:
if (condition1) { ... } else if (condition2) { ... } else { ... }不要寫頭重腳輕的
if塊else。代碼如:if (condition1) { imagine(); that(); there(); are(); many(); many(); many(); lines(); ofCode(); if (condition2) { withNested(); blocks(); } else { that(); require(); scrolling(); } } else { someSingleLineOfCode(); }通常比反轉條件并將更短的塊放在頂部更難遵循:
if (!condition1) { someSingleLineOfCode(); } else { imagine(); that(); there(); are(); many(); many(); many(); lines(); ofCode(); if (condition2) { withNested(); blocks(); } else { that(); require(); scrolling(); } }else通過利用早期退出來取消縮進塊:if (condition1) { return someWidget; } else { lots(); of(); other(); code(); return someOtherWidget; }可:
if (condition1) { return someWidget; } lots(); of(); other(); code(); return someOtherWidget;嘗試強調不同案例中哪些部分相同,哪些部分不同。例子:
if (myReservationsDetailState.attendanceStatus == "Attended") { return Center(child: Text("Thank you for your visit")); } else { return Center(child: Text("Please join next time")); }可以變成:
return Center( child: Text(myReservationsDetailState.attendanceStatus == "Attended" ? "Thank you for your visit" : "Please join next time"));對于具有多個類似
SizedBox(child: Button(...))情況的部分,我將創建區域變數來捕獲差異并重新排列代碼以便共享公共結構。
把它們放在一起:
Widget _renderReservationState() {
if (reservationsDetailState.isFinished) {
return Center(
child: Text(myReservationsDetailState.attendanceStatus == "Attended"
? "Thank you for your visit"
: "Please join next time"));
}
if (reservationsDetailState.rsvpStatus == "Attending" &&
reservationsDetailState.attendanceStatus == "Attended") {
return Center(child: Text("Registration completed"));
}
VoidCallback onButtonPressed;
String buttonTitle;
if (reservationsDetailState.rsvpStatus != "Attending") {
onButtonPressed = () => _confirmReservation(
dateController.text, timeController.text, attendeeController.text);
buttonTitle = "Make a reservation";
} else if (!reservationsDetailState.isEditing) {
onButtonPressed = () => _setEditMode(!myReservationsDetailState.isEditing);
buttonTitle = "Edit reservation";
} else {
onButtonPressed = () {
if (reservationsDetailState.isEditing) {
_confirmReservation(
dateController.text, timeController.text, attendeeController.text);
} else {
_setEditMode(true);
}
};
buttonTitle = "Confirm reservation";
}
return SizedBox(
child: Button(onPressed: onButtonPressed, title: buttonTitle),
width: double.infinity);
}
這仍然很丑陋,但它的縮進明顯減少了,在我看來比原來的要好。
uj5u.com熱心網友回復:
這看起來像是對聯合型別的一種很好的使用。讓我嘗試將其與ifs 和switches 進行比較。
當您必須以各種不同的方式處理多個值組合時,有時不可避免地會出現這樣的代碼。你在這里的選擇是:
if像您所做的嵌套陳述句- 嵌套
switch陳述句 - 使用帶有包的聯合型別,例如freezed。
讓我們考慮一下每種方法的優缺點:
- 嵌套
if陳述句:
- 易于上手
- 最少的壓痕
- (!)分組案例
||有點尷尬 - (!) 容易忘記某些情況
- (!)必須記住在出現新案例時編輯代碼
- 嵌套
switch陳述句:
- 相對容易打字
- 可以輕松清晰地對案例進行分組
- (!) 額外的縮進級別
- (!)案例共享區域變數
- 使用列舉,IDE 可以為丟失的案例提供警告。所以下面兩個可以緩解
- (!) 容易忘記某些情況
- (!)必須記住在出現新案例時編輯代碼
- 聯合型別
- 強制您涵蓋所有情況。使忘記案例成為編譯時錯誤。
- 添加新案例時,現有代碼無法編譯,直到您在任何地方覆寫新案例。
- 案例成為物件而不是簡單的值,您可以為它們添加額外的職責。
- (!)凍結的情況下無法分組,只有一個“其他”情況下使用
orElse. - (!) 額外的縮進級別和額外的閉包語法
- (!) 需要額外的步驟。凍結后,您必須創建這些類并運行 build_runner 來生成代碼。
我相信這些是主要的選擇。當您處于這種情況并且您對自己或隊友有一天會忘記案件感到不安時,嘗試凍結工會課程可能是個好主意。盡管有諸多不便,但涵蓋它提供的所有案例的想法是無價的。
從包中借用示例,當您有一個具有不同情況的聯合類時,如下所示:
@freezed
class Union with _$Union {
const factory Union(int value) = Data;
const factory Union.loading() = Loading;
const factory Union.error([String? message]) = ErrorDetails;
}
你像這樣使用它。不提供任何引數when是編譯時錯誤。所以你可以確定你不會忘記任何案例:
var union = Union(42);
print(
union.when(
(int value) => 'Data $data',
loading: () => 'loading',
error: (String? message) => 'Error: $message',
),
); // Data 42
在您的情況下,您可以為每個變數創建單獨的聯合型別,也可以創建一個表示這些變陣列合的聯合型別。所以你可以有
@freezed
class IsFinished with _$IsFinished {
const factory IsFinished.finished() = Finished;
const factory IsFinished.notFinished() = NotFinished;
}
@freezed
class RsvpStatus with _$RsvpStatus {
const factory RsvpStatus.none() = None;
const factory RsvpStatus.rsvpd() = Rsvpd;
const factory RsvpStatus.canceled() = Canceled;
}
// usage
Widget w = isFinished.when(
finished: () => isRsvpd.when(
none: () => Text('finished and no rsvp'),
rsvpd: () => Text('finished and rsvpd'),
cancelled: () => Text('finished and canceled'),
),
notFinished: () => isRsvpd.when(
none: () => Text('not finished and no rsvp'),
rsvpd: () => Text('not finished and rsvpd'),
cancelled: () => Text('not finished and canceled'),
),
);
或一個具有諸如finishedRsvpd. 在任何一種情況下,忘記一個大小寫都是編譯時錯誤,你會對你的代碼感到更自在。
uj5u.com熱心網友回復:
如果您將代碼拆分為許多較小的函式或自定義小部件,您將幫自己一個忙并大大提高代碼的可讀性。這樣你就可以擺脫極端的、不可讀的嵌套。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/449333.html
