ฉันจะจัดรูปแบบเงื่อนไขของฉันให้ดีขึ้นได้อย่างไร


35

ฉันมีเงื่อนไข

if(exists && !isDirectory || !exists)
{}

ฉันจะแก้ไขได้อย่างไรเพื่อให้เข้าใจได้มากขึ้น


1
isDirectory มีค่าเท่าใดเมื่อมีอยู่เป็นเท็จ
marktani

1
มีอยู่คือประเภทบูล, isDirectory เป็นตัวแปรประเภทบูลด้วย
Spynet

5
ถ้า (! isDirectory) ... (มีอยู่ ||! มีอยู่) จะเป็นจริงเสมอ
ฉลาม

@Shark - จะเกิดอะไรขึ้นถ้าexistsและisDirectoryทั้งสองเป็นความจริง?
Pasawaya

ฉันอ่านชื่อเรื่องว่า "ฉันมีปัญหาบุคลิกภาพฉันสามารถลบความคิดของฉันเพื่อแก้ไขได้" ใช่ฉันเหนื่อย
Annan

คำตอบ:


110

|| เปลี่ยนเป็นอย่างนั้น

if(!exists || (exists && !isDirectory))

เทียบเท่า

ตอนนี้เพราะมีอยู่จริงเสมอในส่วนที่สองของ||คุณสามารถวาง&&:

if(!exists || !isDirectory)

หรือคุณสามารถก้าวไปอีกขั้นแล้วทำ:

if(!(exists && isDirectory))

5
อะไรก็ส่อให้เห็น แต่ไม่ได้กล่าวถึงที่นี่อย่างชัดเจนคือการที่&&มีความสำคัญสูง (อย่างน้อยในส่วนภาษาที่รู้จักกันดี - อาจมีข้อยกเว้น) ||มากกว่า ดังนั้นa && b || cจะเทียบเท่ากับการแต่ไม่ได้ไป(a && b) || c a && (b || c)
PéterTörök

27
ผมคิดว่า!exists || !isDirectoryมีมากขึ้น "เข้าใจ" เพราะไม่สามารถเป็นจริงถ้าisDirectory !existsดังนั้นในฐานะมนุษย์เราจะพูดว่า "ถ้ามันไม่มีตัวตนหรือมัน [มีอยู่แล้ว] ไม่ใช่ไดเรกทอรี"
duros

6
ฉันชอบ! ! isDirectory เหนืออันสุดท้าย
Apoorv Khurasia

3
||เป็นเพียงการสับเปลี่ยนถ้าใช้กับค่าที่ไม่มีผลข้างเคียง - ถ้าเช่นใช้กับฟังก์ชั่นบางฟังก์ชั่นอาจไม่ได้รับการเรียก (ลัดวงจร) หรือคืนค่าที่แตกต่างกันในลำดับที่แตกต่างกัน
orlp

26
ทุกคนที่อาศัยความสำคัญเหนือกว่าของ '&&', '||', '==', '! =', ฯลฯ และไม่ได้แสดงเจตนาที่ชัดเจนโดยใช้วงเล็บที่ควรได้รับการยิง ในทุกภาษามีอะไรบางอย่างเช่น 'a && b || c 'เทียบเท่ากับความคิดเห็นที่บอกว่าผู้เขียนอาจทำให้ทุกอย่างเร่งรีบเพื่อหลีกเลี่ยงการพิมพ์อักขระพิเศษบางอย่าง
เบรนแดน

51

เป็นกระบวนการที่ฉันแนะนำให้สร้างตารางความจริง:

e = exists
d = isDirectory

e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0

สิ่งนี้ตรงกับการNANDดำเนินการซึ่งก็คือ:

!(exists && isDirectory)

หากคุณจำไม่ได้ว่าประตูตรรกะทั้งหมดของคุณวิกิพีเดียมีการอ้างอิงที่ดีกับความจริงโต๊ะบูต


@Christoffer Hammarströmนำขึ้นมาเป็นจุดสำคัญเกี่ยวกับสถานะของถูกผูกติดอยู่กับสถานะของisDirectory existsสมมติว่าพวกเขาอ้างถึงการอ้างอิงเดียวกันและเป็นไปไม่ได้ที่จะมีสถานะที่ไม่มีการอ้างอิงและเป็นไดเรกทอรีตารางความจริงสามารถเขียนได้ดังนี้:

e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | n/a
1 | 0 | 1
1 | 1 | 0

n/aจะใช้ในการเป็นตัวแทนของรัฐที่ไม่ได้เรื่อง ลดการได้รับการยอมรับอาจส่งผลอย่างใดอย่างหนึ่ง1หรือสำหรับรัฐที่เกิดขึ้นใน0n/a

ด้วยวิธีนี้ในใจ!(exists && isDirectory)ก็ยังคงเป็นที่ถูกต้องลดลงส่งผลให้สำหรับ1!e && d

แต่!isDirectoryจะลดลงง่ายมากส่งผลให้ในสำหรับ0!e && d


4
ขั้นตอนต่อไปคือการตระหนักว่าขึ้นอยู่กับisDirectory existsมันไม่สามารถเป็นทั้งไดเรกทอรีและไม่มีอยู่จริง
Christoffer Hammarström

@ChristofferHammarstrom, นอกบริบทฉันไม่สามารถสรุปได้ว่าตัวแปรอ้างถึงสิ่งเดียวกัน แต่นั่นเป็นจุดที่ถูกต้อง คอลัมน์ผลลัพธ์ควรเต็มไปด้วยn/aในสถานที่ที่รัฐไม่สามารถบรรลุได้และสมการลดลงตามลำดับ
zzzzBov

ดีถ้าตัวแปรอ้างถึงบริบทที่แตกต่างกันสองคนพวกเขาจะสั้นเกินไปและจำเป็นต้องเปลี่ยนชื่อ
Christoffer Hammarström

แต่การสร้างตารางความจริงและประเมินว่าสมบูรณ์แล้ว!
Thomas Eding

@ThomasEding ฉันมีสองใบเสนอราคาสำหรับคุณแล้ว "ในทางทฤษฎีทฤษฎีและการปฏิบัติเหมือนกัน; ในทางปฏิบัติพวกเขาไม่ได้" และ "การเพิ่มประสิทธิภาพก่อนกำหนดเป็นรากฐานของความชั่วร้ายทั้งหมด"
zzzzBov

22

เพื่อการอ่านที่ดีขึ้นฉันชอบแยกเงื่อนไขบูลีนเป็นวิธีการ:

if(fileNameUnused())
{...}

public boolean fileNameUnused() {
   return exists && !isDirectory || !exists;
}

หรือด้วยชื่อวิธีที่ดีกว่า หากคุณสามารถตั้งชื่อวิธีการนี้ได้อย่างเหมาะสมผู้อ่านรหัสของคุณไม่จำเป็นต้องทราบว่าเงื่อนไขบูลีนหมายถึงอะไร


+1 สำหรับพูดบางอย่างเกี่ยวกับชื่อที่มีประโยชน์ แต่คุณจะต้องจัดรูปแบบตามเงื่อนไขใหม่
Apoorv Khurasia

4
ทางเลือกที่น้อยที่สุดที่ยังคงสื่อถึงความตั้งใจนั้นเป็นเพียงการตั้งชื่อสภาพที่ใช้:boolean fileNameUnused = !exists || !isDirectory; if (fileNameUnused) { doSomething(); }
Steven

8

คุณสามารถลองทำเคสที่ไม่ต้องไปและประกันตัวถ้ามันปรากฏขึ้น

while(someCondition) {

    if(exists && isDirectory)
        continue;
        // maybe "break", depends on what you're after.

        // the rest of the code
}

หรือแม้กระทั่ง

function processFile(someFile)
{ 
    // ...
    if(exists && isDirectory)
       return false;
    // the rest of the code
    // ...
}

คำสั่งการส่งคืนที่ผิดพลาดดำเนินการต่อและมากกว่าหนึ่งจะถือว่ามีกลิ่นรหัสหรือไม่
Freiheit

8
@ ฟรีมันขึ้นอยู่กับบริบท บางครั้งมีการใช้คำสั่ง return ก่อนหน้าเพื่อลดการเยื้องจึงช่วยให้อ่านง่ายขึ้น
marco-fiset

คำตอบที่ดีที่สุด - เงื่อนไขที่ซับซ้อนทำให้เสียเวลาอ่านจำนวนมหาศาลและเข้าใจพวกเขาอย่างแม่นยำ เป็นผลให้มักจะ "นำมาเป็นอ่าน" นำไปสู่ข้อบกพร่องร้ายกาจ
mattnz

6

คุณสามารถใช้ตารางความจริงตามที่ระบุไว้ ขั้นตอนที่สองอาจเป็นแผนที่ KVสำหรับการลดจำนวนคำศัพท์

การใช้กฎของพีชคณิตแบบบูลเป็นอีกแนวทางหนึ่ง:

A = มีอยู่
B =! isDirectory
! A =! มีอยู่

&& = *
|| = +

[แก้ไข]
การแปลงที่ง่ายกว่าเนื่องจากการดำเนินการ AND และ OR มีการแจกจ่ายซึ่งกันและกัน:

มีอยู่ &&! isDirectory || ! อยู่
= A * B +! A
= (A +! A) * (B +! A)
= 1 * (B +! A)
= B +! A
[/ แก้ไข]

มีอยู่ &&! isDirectory || ! อยู่
= A * B +! A
= A * B +! A * 1 // ตัวตน
= A * B +! A * (B + 1) // Annihilator
= A * B +! A * B +! A / / การกระจายและเอกลักษณ์
= B * (A +! A) +! A // การกระจาย
= B * 1 +! A // การประกอบ 2
= B +! A // เอกลักษณ์
=! isDirectory || ! อยู่

หรือเติมเต็มสองครั้ง (!! x = x):

A * B +! A
= !! (A * B +! A)
=! (! (A * B) * A)
=! ((! A +! B) * A)
=! (! A * A + ! B * A)
=! (0 +! B * A)
=! (! B * A)
= B +! A
=! isDirectory || ! อยู่


+1 สำหรับการใช้กฎอย่างเป็นทางการ (ฉันไม่เคยคิดเลยว่าจะได้เห็นสิ่งใดสิ่งหนึ่งหลังจากเรียนจบปีแรก)
Nemanja Boric


5

ฉันไม่ชอบใช้ "!" เมื่อมีมากกว่าหนึ่งเงื่อนไขในการแสดงออก ฉันจะเพิ่มบรรทัดของรหัสเพื่อให้อ่านง่ายขึ้น

doesNotExist = !exists;
isFile = exists && !isDirecotry;
if (isFile || doesNotExist) 
   {}

+1 สิ่งนี้ทำให้ง่ายต่อการอ่านว่า "ถ้าเป็นไฟล์หรือไม่มีอยู่" ซึ่งใกล้เคียงกับภาษาอังกฤษมาก
ฟิล

นี่คือ refactoring ที่เรียกว่าแนะนำอธิบายตัวแปร
Eddie Gasparian

1

ตามที่ระบุไว้ก่อนหน้านี้เงื่อนไขสามารถลดลงเป็น:

if (!(exists && isDirectory))

อย่างไรก็ตามฉันจะเดิมพันว่าการเป็นไดเรกทอรีหมายถึงการมีอยู่ ถ้าเป็นเช่นนั้นเราสามารถลดเงื่อนไขเป็น:

if (!isDirectory)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.