Home > Software engineering >  Is there a better way to write a nested if-else such as this?
Is there a better way to write a nested if-else such as this?

Time:03-23

Below is a snippet of code for a flutter function returning a widget. It either returns a button or text widget depending on four different variables.

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");)
            }
          }
        }

The existing code was a nested if-else over a couple hundred lines. I've refactored it to be shorter but I'm not happy with this implementation either. Any suggestions or recommendations would be appreciated.

CodePudding user response:

You will do yourself a favor and improve the readability of the code substantially if you split it up into many smaller functions or CustomWidgets. That way you can get rid of the extreme, unreadable nesting.

CodePudding user response:

When there are a combination of values that you have to act in various different ways, it is sometimes inevitable to end up with code like this. You options here are:

  1. Nested if statements like you have done
  2. Nested switch statements
  3. Using union types with a package such as freezed.

Let's think about the pros and cons of each:

  1. Nested if statements:
  • Easy to get started with
  • Least amount of indentation
  • (!) Grouping cases with || is somewhat awkward
  • (!) Easy to forget some cases
  • (!) Have to remember to edit code when new cases appear
  1. Nested switch statements:
  • Relatively easy to type
  • Can group cases easily and clearly
  • (!) Extra levels of indentation
  • (!) Cases share local variables
  • With enums, IDEs can provide warnings for missing cases. So the following two can be alleviated
  • (!) Easy to forget some cases
  • (!) Have to remember to edit code when new cases appear
  1. Union types
  • Forces you to cover all cases. Makes it a compile-time error to forget cases.
  • When new cases are added, existing code cannot compile until you cover the new case everywhere.
  • Cases become objects rather than simple values, you can add extra responsibilities to them.
  • (!) Grouping of cases is not possible with freezed, there is a single "others" case with orElse.
  • (!) Extra levels of indentation and extra closure syntax
  • (!) Requires an extra step. With freezed you have to create those clasess and run build_runner to generate code.

I believe these are the main options. When you are in this situation and you feel uneasy that you or a teammate can forget a case someday, it's probably a good idea to give union classes with freezed a try. Despite its inconveniences, the piece of mind about covering all cases that it provides is invaluable.

  • Related