Memeriksa apakah suatu metode mengembalikan false: menugaskan hasil ke variabel sementara, atau menempatkan pemanggilan metode secara langsung dalam kondisi?

9

Apakah praktik yang baik untuk memanggil metode yang mengembalikan nilai benar atau salah dalam pernyataan if?

Sesuatu seperti ini:

private void VerifyAccount()
{
    if (!ValidateCredentials(txtUser.Text, txtPassword.Text))
    {
        MessageBox.Show("Invalid user name or password");
    }
}

private bool ValidateCredentials(string userName, string password)
{
    string existingPassword = GetUserPassword(userName);
    if (existingPassword == null)
        return false;

    var hasher = new Hasher { SaltSize = 16 };
    bool passwordsMatch = hasher.CompareStringToHash(password, existingPassword);

    return passwordsMatch;
}

atau apakah lebih baik menyimpannya dalam suatu variabel kemudian membandingkannya menggunakan jika ada nilai-nilai seperti ini

bool validate = ValidateCredentials(txtUser.Text, txtPassword.Text);
if(validate == false){
    //Do something
}

Saya tidak hanya merujuk pada .NET, saya merujuk pada pertanyaan dalam semua bahasa pemrograman, kebetulan saya menggunakan .NET sebagai contoh.

KyelJmD
sumber
3
Jika Anda menggunakan variabel sementara, menulis if (!validate)bukan if (validate == false).
Philip
12
Saya akan beri nama fungsi seperti "CredentialsAreValid ()" jadi Anda tahu itu harus mengembalikan bool tetapi sebaliknya ya praktik yang baik
Zachary K
3
IsValidCredentials, meskipun secara tata bahasa canggung, adalah format umum untuk menunjukkan nilai pengembalian boolean.
zzzzBov
@ Pilip apa bedanya if (! Validate) dan this if (validate) ??
KyelJmD
!adalah operator "BUKAN", itu meniadakan ekspresi boolean. Begitu if (!validate)juga sebaliknya if (validate). Pernyataan if akan dimasukkan jika validatetidak benar.
Philip

Jawaban:

26

Seperti semua hal ini tergantung.

Jika Anda tidak akan menggunakan hasil panggilan Anda ValidateCredentialsmaka tidak perlu (selain untuk keperluan debugging) untuk menyimpan hasilnya dalam variabel lokal. Namun, jika itu membuat kode lebih mudah dibaca (dan karenanya lebih dapat dipelihara) untuk memiliki variabel pergi dengan itu.

Kode tidak akan kurang efisien secara terukur.

ChrisF
sumber
1
Apakah jenis itu dapat dibaca? seperti yang saya lakukan di atas
KyelJmD
@KyelJmD: Itu tergantung pada budaya yang Anda pemrograman. Di tempat saya diprogram, !ValidateCredentialslebih mudah dibaca karena secara eksplisit mengatakan apa yang dilakukannya dalam kode. Sangat jelas. Jika fungsi yang Anda panggil tidak memiliki nama "mendokumentasikan sendiri" maka mungkin lebih baik untuk pergi dengan variabel. Seperti berdiri, saya akan merekomendasikan menghilangkan variabel dan tetap dengan kode dokumentasi diri yang Anda miliki.
Joel Etherton
ValidateCredentials tidak dapat dibaca sejak awal - bagaimana namanya memberi tahu Anda apa artinya hasilnya? Jauh lebih baik CredentialsAreValid atau CredentialsAreInvalid.
gnasher729
9

Mengapa menggunakan variabel tambahan? Saya lebih suka menggunakan pendekatan pertama, lebih mudah dibaca dan sederhana.

Diego Pacheco
sumber
4

Apakah praktik yang baik untuk memanggil metode yang mengembalikan nilai benar atau salah dalam pernyataan if?

Ya, jika persyaratannya tidak cukup sederhana untuk sebaris dan membuatnya dapat dibaca.

atau apakah lebih baik menyimpannya dalam suatu variabel kemudian membandingkannya menggunakan jika ada nilai-nilai seperti ini

Anda hanya harus melakukan ini jika Anda menggunakan nilai di banyak tempat atau memerlukannya untuk membuat kode lebih mudah dibaca. Kalau tidak, penugasan ke variabel tidak perlu. Kode yang tidak perlu paling tidak boros dan paling buruk merupakan sumber cacat.

dietbuddha
sumber
2

Biarkan melihat...

Karena ini semua tentang KISS , tidak perlu membuat variabel tambahan ketika Anda bisa melakukannya tanpa itu. Juga, tidak perlu mengetik lagi ... saat tidak perlu.

Tetapi karena Anda KERING , jika nanti Anda menelepon ValidateCredentialsdan menemukan diri ValidateCredentials(txtUser.Text, txtPassword.Text)Anda mengetik, Anda tahu Anda harus membuat variabel tambahan.

kowsheek
sumber
2

Ya, biasanya baik-baik saja untuk menggunakan metode seperti jika kondisi. Akan sangat membantu jika nama metode menunjukkan bahwa metode mengembalikan bool; misalnya CanValidateCredentials. Dalam bahasa C-style metode ini sering mengambil bentuk awalan Is and Can, dan di Ruby dengan '?' akhiran.

Christian Horsdal
sumber
1
Poin bagus tentang nama metode, tapi saya tidak akan pernah memulai nama metode dengan "jika". Kemudian kode bertuliskan "jika jika". "Can" ok: if (cat.canOpenCanOfCatFood()).
kevin cline
Terima kasih, @Kevin. Maksud saya 'Apakah' bukan 'Jika'. Saya mengedit jawabannya
Christian Horsdal
1

Ada kekhawatiran lain yang belum ditunjukkan: evaluasi hubungan pendek . Apa perbedaan antara kedua fragmen kode ini?

Kelima # 1:

if(foo() && bar() && baz())
{
    quz();
}

Kelima # 2:

bool isFoo = foo();
bool isBar = bar();
bool isBaz = baz();
if(isFoo && isBar && isBaz)
{
    quz();
}

Kedua fragmen kode ini tampaknya melakukan hal yang sama, tetapi jika bahasa Anda mendukung evaluasi hubung singkat, kedua fragmen ini berbeda. Evaluasi hubungan pendek berarti bahwa kode akan mengevaluasi minimum yang diperlukan untuk melewati atau gagal suatu kondisi. Jika contoh # 1, jika foo () mengembalikan false, bar () dan baz () bahkan tidak dievaluasi. Ini berguna jika baz () adalah panggilan fungsi yang telah berjalan lama karena Anda dapat melewatkannya jika foo () mengembalikan false atau foo () mengembalikan true dan bar () mengembalikan false.

Ini tidak terjadi pada contoh # 2. foo (), bar (), dan baz () selalu dievaluasi. Jika Anda mengharapkan bilah () dan baz () menunjukkan efek samping, Anda akan mengalami masalah dengan Contoh # 1. Contoh # 1 di atas sebenarnya setara dengan ini:

Kelima #:

if(foo())
{
    if(bar())
    {
        if(baz())
        {
            quz();
        }
    }
}

Waspadai perbedaan ini dalam kode Anda saat memilih antara contoh # 1 dan # 2.

pengguna2023861
sumber
1

Memperluas sedikit pada masalah keterbacaan ...

Saya dapat memikirkan dua alasan bagus untuk menyimpan hasilnya dalam sebuah variabel:

  1. Jika Anda akan menggunakan kondisi lebih dari sekali, menyimpannya dalam variabel berarti Anda hanya perlu memanggil fungsi satu kali. (Ini mengasumsikan bahwa nilai yang disimpan masih valid; jika Anda perlu mengujinya kembali, tentu saja ini tidak berlaku.)

  2. Jika menyimpannya dalam variabel meningkatkan keterbacaan dengan memberikan kondisi nama yang lebih bermakna daripada apa yang Anda lihat dalam panggilan fungsi.

Sebagai contoh, ini:

bool foo_is_ok = is_ok(foo);
if (foo_is_ok) ...

tidak membantu keterbacaan, tetapi ini:

bool done_processing = feof(file1) && feof(file2);
if (done_processing) ...

mungkin tidak, karena tidak segera jelas itu feof(file1) && feof(file2)berarti bahwa kami sudah selesai memproses.

The passwordsMatchvariabel dalam pertanyaan mungkin contoh yang lebih baik dari saya.

Variabel sekali pakai berguna jika mereka memberikan nama yang berarti untuk beberapa nilai. (Ini tentu saja untuk kepentingan pembaca manusia.)

Keith Thompson
sumber
Saya pikir, saya lebih suka memberikan komentar daripada memperkenalkan done_processingvariabel. Lagi pula, nama itu done_processingberfungsi sebagai komentar. Dan komentar nyata memungkinkan saya untuk mengatakan satu atau dua kata tentang mengapa kondisi ini menandakan kami selesai memproses. Bukannya aku seorang komentator hebat, mungkin aku tidak akan melakukan keduanya dalam kode nyata ...
cmaster - mengembalikan monica
@ cmaster: Satu masalah dengan komentar adalah mereka dapat dengan mudah keluar dari sinkronisasi dengan kode. Variabel bernama done_processingadalah cara yang lebih tahan lama untuk mengekspresikan maksud.
Keith Thompson
+1 untuk poin nomor 2 - terkadang temp var yang bernama baik benar-benar menjelaskan hal-hal.
user949300