Skip to content

Latest commit

ย 

History

History
346 lines (315 loc) ยท 12.6 KB

Section7.md

File metadata and controls

346 lines (315 loc) ยท 12.6 KB

7์žฅ ์˜ค๋ฅ˜์ฒ˜๋ฆฌ

์˜ค๋ฅ˜ ์ฝ”๋“œ๋ณด๋‹ค ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

์˜ค๋ฅ˜ ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ•˜๊ฑฐ๋‚˜, ํ˜ธ์ถœ์ž์—๊ฒŒ ์˜ค๋ฅ˜ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์˜ˆ์‹œ

public void sendShutDown(){
    DeviceHandle handle = getHandle(DEV1);
    // ๋””๋ฐ”์ด์Šค ์ƒํƒœ ์ ๊ฒ€.
    if(handle != DeviceHandle.INVALID){
        // ๋ ˆ์ฝ”๋“œ ํ•„๋“œ์— ๋””๋ฐ”์ด์Šค ์ƒํƒœ ์ €์žฅ
        retrieveDeviceRecord(handle);
        // ๋””๋ฐ”์ด์Šค๊ฐ€ ์ผ์‹œ์ •์ง€ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ข…๋ฃŒ.
        if (record.getStatus() != DEVICE_SUSPENDED){
            closeDevice(handle);
        }
        else{
            logger.log("Device suspended. Unable to shut down");
        }
    }
    else {
        logger.log("Invalid handle for : " + DEV1.toString());
    }
}

์ฝ”๋“œ์˜ Depth๊ฐ€ ๊นŠ์–ด์ง€๋ฉด์„œ ํ”„๋กœ๊ทธ๋žจ ๋กœ์ง๊ณผ ์˜ค๋ฅ˜์ฒ˜๋ฆฌ์ฝ”๋“œ๊ฐ€ ๋’ค์„ž์ด๊ธฐ๋•Œ๋ฌธ์— ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง„๋‹ค.

์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋Š” ์˜ˆ์‹œ

public void sendShutDown(){
    try {
        tryToShutDown();
    } 
    catch (DeviceShutDownError e){
      logger.log(e);  
    }
}

// ํ”„๋กœ๊ทธ๋žจ ๋กœ์ง
private void tryToShutDown() throws DeviceShutDownError {
    DeviceHandle handle = getHandle(DEV1);
    DeviceRecord record = retrieveDeviceRecord(handle);
    
    closeDevice(handle);
}

private DeviceHandle getHandle(DeviceID id){
    ...
    throw new DeviceShutDownError("Invalid handle for : " + id.toString())
}
...

๋””๋ฐ”์ด์Šค๋ฅผ ์ข…๋ฃŒํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฝ”๋“œ ํ’ˆ์งˆ์ด ๋‚˜์•„์กŒ๋‹ค.

Try-Catch-Finally ๋ฌธ๋ถ€ํ„ฐ ์ž‘์„ฑํ•˜๋ผ

  • ์˜ˆ์™ธ๋Š” ํ”„๋กœ๊ทธ๋žจ์•ˆ์— ๋ฒ”์œ„๋ฅผ ์ •์˜ํ•œ๋‹ค
    • try ๋ธ”๋ก์— ๋“ค์–ด๊ฐ€๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, ์–ด๋Š ์‹œ์ ์—์„œ๋“  ์‹คํ–‰์ด ์ค‘๋‹จ๋œ ํ›„ catch ๋ธ”๋ก์œผ๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.
  • try๋ธ”๋ก์€ ํŠธ๋žœ์žญ์…˜๊ณผ ๋น„์Šทํ•˜๋‹ค.
    • try ๋ธ”๋ก์—์„œ ๋ฌด์Šจ ์ผ์ด ์ƒ๊ธฐ๋“  catch ๋ธ”๋ก์€ ํ”„๋กœ๊ทธ๋žจ ์ƒํƒœ๋ฅผ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์œ ์ง€ํ•ด์•ผํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์งค ๋•Œ try-catch-finally๋ฌธ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํŽธ์ด ์ข‹๋‹ค.

try๋ธ”๋ก์—์„œ ๋ฌด์Šจ ์ผ์ด ์ƒ๊ธฐ๋“ , ํ˜ธ์ถœ์ž๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ์ƒํƒœ๋ฅผ ์ •์˜ํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค.

TDD๋ฅผ ์‚ฌ์šฉํ•œ try-catch ๋ฒ”์œ„ ์ •์˜ํ•˜๊ธฐ

  1. ๊ฐ•์ œ๋กœ ์˜ˆ์™ธ๋ฅผ ์ผ์œผํ‚ค๋Š” ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
@Test(expected = StorageException.class)
public void retrieveSectionShouldThrowOnInvalidFileName() {
    sectionStore.retrieveSection("invalid - file");
}
  1. ๋‹จ์œ„ํ…Œ์ŠคํŠธ์— ๋งž์ถฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.
public List<RecordedGrip> retrieveSection(String sectionName) {
    // ์‹ค์ œ ๊ตฌํ˜„์ „๊นŒ์ง€ ๋”๋ฏธ ๋ฐ˜ํ™˜.
    return new ArrayList<RecordedGrip>();
}
  1. ํ…Œ์ŠคํŠธ ์‹คํŒจ ํ›„ ์„ฑ๊ณตํ•˜๋„๋ก ๊ตฌํ˜„์„ ๋ณ€๊ฒฝํ•œ๋‹ค.
public List<RecordedGrip> retrieveSection(String sectionName){
    try {
        FileInputStream stream = new FileInputStream(sectionName);
    } 
    catch (Exception e){
        throw new StorageException("retrival error", e);
    }
    return new ArrayList<RecordedGrip>();
}
  1. ํ…Œ์ŠคํŠธ ์„ฑ๊ณต ํ›„ ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•œ๋‹ค.
public List<RecordedGrip> retrieveSection(String sectionName){
    try {
        FileInputStream stream = new FileInputStream(sectionName);
        stream.close();
    }
    catch (FileNotFoundException e){ // ์˜ˆ์™ธ ์œ ํ˜•์„ ์ขํžŒ๋‹ค.
        throw new StorageException("retrival error", e);
    }
    return new ArrayList<RecordedGrip>();
}

๊ฐ•์ œ๋กœ ์˜ˆ์™ธ๋ฅผ ์ผ์œผํ‚ค๋Š” ํ…Œ์ŠคํŠธ์ผ€์ด์Šค๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ try๋ธ”๋ก์˜ ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„๋ถ€ํ„ฐ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ๋ฒ”์œ„ ๋‚ด์—์„œ ํŠธ๋žœ์žญ์…˜ ๋ณธ์งˆ์„ ์œ ์ง€ํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค.

๋ฏธํ™•์ธ(Unchecked) ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

  • ๊ณผ๊ฑฐ์—” ํ™•์ธ๋œ(Checked) ์˜ˆ์™ธ๋ฅผ ๋ฉ‹์ง„ ์•„์ด๋””์–ด๋ผ ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์•ˆ์ •์ ์ธ SW ์ œ์ž‘์— ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•˜์ง€๋Š” ์•Š๋‹ค๋ผ๋Š” ์‚ฌ์‹ค์ด ๋ถ„๋ช…ํ•ด์กŒ๋‹ค.
  • ๊ทธ๋Ÿฌ๋ฏ€๋กœ ํ™•์ธ๋œ ์˜ˆ์™ธ๊ฐ€ ์น˜๋ฅด๋Š” ๋น„์šฉ์— ์ƒ์Šนํ•˜๋Š” ์ด์ต์„ ์ œ๊ณตํ•˜๋Š”์ง€ ๋”ฐ์ ธ๋ด์•ผํ•œ๋‹ค.
  • ์ด ๋น„์šฉ์ด๋ž€ ? ํ™•์ธ๋œ ์˜ˆ์™ธ๋Š” OCP(Open Closed Principle)์„ ์œ„๋ฐ˜ํ•œ๋‹ค.
public void ex() {
  try {
    a();
  }
  catch(AWTException e){
      log.error(e);
  }
  catch(SQLException e){
      log.error(e);
  }
  catch(IOException e){
      log.error(e);
  }
}

// ์ตœํ•˜์œ„ ๋ฉ”์„œ๋“œ๋ถ€ํ„ฐ ์„ ์–ธ๋œ ๋ชจ๋“  ์˜ˆ์™ธ๋ฅผ ์„ ์–ธํ•ด์ฃผ๊ณ ์žˆ๋‹ค. (์ปดํŒŒ์ผ๋Ÿฌ ๊ฐ•์ œ)
public void a() throws AWTException, SQLException, IOException {
  b();
  throw new AWTException("exception");
}

public void b() throws SQLException, IOException{
  c();
  throw new SQLException();
}

public void c() throws IOException {
  throw new IOException();
}
  • ๋ชจ๋“  ํ•จ์ˆ˜๊ฐ€ ์ตœํ•˜์œ„ ๋ฉ”์„œ๋“œ์—์„œ ๋˜์ง€๋Š” ์˜ˆ์™ธ๋ฅผ ์•Œ๊ณ  ์ฒ˜๋ฆฌํ•ด์ฃผ์–ด์•ผ ํ•˜๊ธฐ๋•Œ๋ฌธ์— ์บก์Šํ™”๊ฐ€ ๊นจ์ง„๋‹ค.
  • ๋งŒ์•ฝ ์ตœํ•˜์œ„ ๋ฉ”์„œ๋“œ์ธ c์˜ Exception์„ ์ˆ˜์ •ํ•œ๋‹ค๋ฉด, ๋กœ์ง์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋”๋ผ๋„ ๋ชจ๋“  ์ƒ์œ„ ๋ฉ”์„œ๋“œ(b, a, ex)๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝํ•ด์•ผํ•œ๋‹ค. (OCP ์œ„๋ฐ˜)

์•„์ฃผ ์ค‘์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, ๋ชจ๋“  ์˜ˆ์™ธ๋ฅผ ์žก๋Š”๊ฒŒ ๋งž์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์˜์กด์„ฑ์ด๋ผ๋Š” ๋น„์šฉ์ด ์ด์ต๋ณด๋‹ค ํฌ๋‹ค

Java์—์„œ ์˜ˆ์™ธ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-06 แ„‹แ…ฉแ„’แ…ฎ 5 41 23
  • Checked Exception : Exception์„ ์ƒ์†ํ•˜๋Š” ์˜ˆ์™ธ. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ•์ œ(ํ™•์ธ)ํ•˜๋Š” ์˜ˆ์™ธ.
    • ์‚ฌ์šฉ์ž(์™ธ๋ถ€)์˜ ๋™์ž‘์— ์˜ํ•ด์„œ ๋ฐœ์ƒ๋  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋“ค
    • ex) ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ์ž…๋ ฅ(FileNotFoundException)
  • Unchecked Exception : RuntimeException์„ ์ƒ์†ํ•˜๋Š” ์˜ˆ์™ธ. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ•์ œ(ํ™•์ธ)ํ•˜์ง€ ์•Š๋Š” ์˜ˆ์™ธ.
    • ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์‹ค์ˆ˜์— ์˜ํ•ด ๋ฐœ์ƒ๋  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋“ค
    • ex) ๋ฐฐ์—ด์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚จ(IndexOutOfBoundsException), null์ธ ์ฐธ์กฐ๋ณ€์ˆ˜์˜ ๋ฉค๋ฒ„๋ฅผ ํ˜ธ์ถœ(NullPointException)

Checked Exception์€ Java์—๋งŒ ์žˆ๋‹ค. ๋‹ค๋ฅธ ์–ธ์–ด(C#, C++, Python ๋“ฑ)๋“ค์—๋Š” ์—†๋‹ค.
์ฐธ๊ณ  : Checked Exception, Unchecked Exception ๊ทธ๋ฆฌ๊ณ  ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

์˜ˆ์™ธ์— ์˜๋ฏธ๋ฅผ ์ œ๊ณตํ•˜๋ผ

  • ์ž๋ฐ”์—์„  ๋ชจ๋“  ์˜ˆ์™ธ์— ํ˜ธ์ถœ ์Šคํƒ์„ ์ œ๊ณตํ•˜์ง€๋งŒ ์‹คํŒจํ•œ ์ฝ”๋“œ์˜ ์˜๋„๋ฅผ ํŒŒ์•…ํ•˜๋ ค๋ฉด ํ˜ธ์ถœ ์Šคํƒ๋งŒ์œผ๋กœ ๋ถ€์กฑํ•˜๋‹ค.
  • ์˜ˆ์™ธ๋ฅผ ๋˜์งˆ ๋•Œ ์ „ํ›„ ์ƒํ™ฉ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์•„ ํ•จ๊ป˜ ๋˜์ง„๋‹ค๋ฉด, ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ์›์ธ๊ณผ ์œ„์น˜๋ฅผ ์ฐพ๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค.
  • ํŠนํžˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊น… ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์˜ค๋ฅ˜๋ฅผ ๊ธฐ๋กํ•˜๋„๋ก ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.

ํ˜ธ์ถœ์ž๋ฅผ ๊ณ ๋ คํ•ด ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋ผ

์˜ค๋ฅ˜๋ฅผ ํ˜•ํŽธ์—†์ด ๋ถ„๋ฅ˜ํ•œ ์˜ˆ์‹œ

ACMEPort port = new ACMEPort(12);

// ์™ธ๋ถ€API๊ฐ€ ๋˜์ง€๋Š” ๋ชจ๋“  ์˜ˆ์™ธ๋ฅผ ์žก์•„๋‚ธ๋‹ค.
try {
    port.open();
}
catch (DeviceResponseException e) {
    reportPortError(e);
    logger.log("Device response exception", e);
}
catch (ATM1212UnlockedException e) {
    reportPortError(e);
    logger.log("Unlock exception", e);
}
catch (GMXError e) {
    reportPortError(e);
    logger.log("Device response exception");
}
finally {
    ...
}

์œ„ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์€ ์˜ค๋ฅ˜ ์œ ํ˜•๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ผ์ •ํ•˜๋‹ค.

  1. ์˜ค๋ฅ˜ ๊ธฐ๋ก
  2. ํ”„๋กœ๊ทธ๋žจ์„ ๊ณ„์† ์ˆ˜ํ–‰ํ•ด๋„ ์ข‹์€์ง€ ํ™•์ธ

Wrapper ํด๋ž˜์Šค๋กœ ์˜ˆ์™ธ๋ฅผ ๊ฐ์‹ธ ๋ณ€ํ™˜ํ•˜๋Š” ์˜ˆ์‹œ

public class LocalPort {
    private ACMEPort innerPort;
    
    public LocalPort(int portNumber) {
        innerPort = new ACMEPort(portNumber);
    }

    // ์™ธ๋ถ€API๊ฐ€ ๋˜์ง€๋Š” ๋ชจ๋“  ์˜ˆ์™ธ๋ฅผ ํ•˜๋‚˜์˜ ์˜ˆ์™ธ๋กœ ๊ฐ์‹ธ์„œ ๋‹ค์‹œ ๋˜์ง„๋‹ค.
    public void open() {
        try {
            innerPort.open();
        } 
        catch (DeviceResponseException e) {
            throw new PortDeviceFailure(e);
        }
        catch (ATM1212UnlockedException e) {
            throw new PortDeviceFailure(e);
        }
        catch (GMXError e) {
            throw new PortDeviceFailure(e);
        }
    }
}
LocalPort port = new LocalPort(12);
try {
   port.open();
}
catch (PortDeviceFailure e) { // ํ•˜๋‚˜์˜ ์˜ˆ์™ธ ์‚ฌ์šฉ
   reportError(e);
   logger.log(e.getMessage(), e);
}
finally {
   ...
}

Wrapper ํด๋ž˜์Šค์˜ ์žฅ์ 

์™ธ๋ถ€ API์™€ ํ”„๋กœ๊ทธ๋žจ ์‚ฌ์ด์—์„œ ์˜์กด์„ฑ์ด ํฌ๊ฒŒ ์ค„์–ด๋“ ๋‹ค.

  • ๋‹ค๋ฅธ API๋กœ ๊ฐˆ์•„ํƒ€๋„ ๋น„์šฉ์ด ์ ๋‹ค.
  • ํ”„๋กœ๊ทธ๋žจ์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค.
  • ์™ธ๋ถ€ API ์„ค๊ณ„ ๋ฐฉ์‹์— ๋ฐœ๋ชฉ์žกํžˆ์ง€ ์•Š๋Š”๋‹ค. (ํ”„๋กœ๊ทธ๋žจ์ด ์‚ฌ์šฉํ•˜๊ธฐ ํŽธ๋ฆฌํ•œ API ์ •์˜ ๊ฐ€๋Šฅ)

์ •์ƒ ํ๋ฆ„์„ ์ •์˜ํ•˜๋ผ

  • ๋•Œ๋กœ๋Š”, ์˜ˆ์™ธ๋ฅผ ๋˜์ ธ ํ”„๋กœ๊ทธ๋žจ์„ ์ค‘๋‹จ์‹œํ‚ค๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ์ ํ•ฉํ•˜์ง€ ์•Š์„ ๋•Œ๊ฐ€ ์žˆ๋‹ค.

์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋Š” ์˜ˆ์‹œ

try {
    MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
    m_total += expenses.getTotal(); // ์ง์›์ด ์ฒญ๊ตฌํ•œ ์‹๋น„๋ฅผ ์ด๊ณ„์— ๋”ํ•จ.
}
catch(MealExpensesNotFound e) { // ์ฒญ๊ตฌํ•œ ์‹๋น„๊ฐ€ ์—†๋‹ค๋ฉด,
    m_total += getMealPerDiem(); // ์ผ์ผ ๊ธฐ๋ณธ ์‹๋น„๋ฅผ ์ด๊ณ„์— ๋”ํ•จ.
}
  • ํŠน์ˆ˜ํ•œ ์ƒํ™ฉ์— ์˜ˆ์™ธ๋ฅผ ๋˜์ ธ ๋ถ„๊ธฐ๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ, ์ด๋Š” ๋…ผ๋ฆฌ๋ฅผ ๋”ฐ๋ผ๊ฐ€๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค.

ํŠน์ˆ˜ ์‚ฌ๋ก€ ํŒจํ„ด ์˜ˆ์‹œ

// ExpenseReportDAO๋Š” ํ•ญ์ƒ MealExpenses๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID()); 
m_total += expenses.getTotal();

public class PerDiemMealExpenses implements MealExpenses {
  public int getTotal() {
    // ์ฒญ๊ตฌ๊ฐ’์ด ์—†๋‹ค๋ฉด, ์ผ์ผ ๊ธฐ๋ณธ ์‹๋น„๋ฅผ ๋ฐ˜ํ™˜
  }
}
  • ํŠน์ˆ˜ ์‚ฌ๋ก€ ํŒจํ„ด : ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ๊ฐ์ฒด๋ฅผ ์กฐ์ž‘ํ•ด ํŠน์ˆ˜ ์‚ฌ๋ก€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹
  • ๊ฐ์ฒด๊ฐ€ ์˜ˆ์™ธ์ ์ธ ์ƒํ™ฉ์„ ์บก์Šํ™”ํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋Š” ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

ํŠน์ˆ˜ ์‚ฌ๋ก€ ํŒจํ„ด์€ ๋งˆํ‹ดํŒŒ์šธ๋Ÿฌ ๋ฆฌํŒฉํ† ๋ง ์ฑ…์—๋„ ์†Œ๊ฐœ๋œ ํŒจํ„ด
์ฐธ๊ณ  : ํŠน์ด ์ผ€์ด์Šค ํŒจํ„ด(Special Case Pattern)

null์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ๋งˆ๋ผ

  • null์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์Šต๊ด€์€ ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.
public void registerItem(Item item) {
     if (item != null) {
         ItemRegistry registry = peristentStore.getItemRegistry(); // peristentStore null ์ฒดํฌ ๋น ์ง.
         if (registry != null) {
             Item existing = registry.getItem(item.getID());
             if (existing.getBillingPeriod().hasRetailOwner()) {
                 existing.register(item);
             }
         }
     }
 }
  • ์œ„ ์˜ˆ์ œ์ฒ˜๋Ÿผ null ์ฒดํฌ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์•„์ง€๋ฉด ์–ด๋”” ํ•œ๊ตฐ๋ฐ์—์„œ ๋นผ๋จน์„ ์‹œ NullPointerException์ด ๋ฐœ์ƒํ•œ๋‹ค.
  • null์„ ๋ฐ˜ํ™˜์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, ๊ทธ ๋Œ€์‹  ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ฑฐ๋‚˜ ํŠน์ˆ˜ ์‚ฌ๋ก€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ์˜ˆ์‹œ : ์ปฌ๋ ‰์…˜์˜ ๊ฒฝ์šฐ null ๋ฐ˜ํ™˜๋ณด๋‹จ ๋นˆ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•˜์ž.
List<Employee> employees = getEmployees();
for(Employee e : Employees) {
    totalPay += e.getPay();
}
public List<Employee> getEmployees() {
    if(์ง์›์ด ์—†๋‹ค๋ฉด) return Colloctions.emptyList();
}

null์„ ์ „๋‹ฌํ•˜์ง€ ๋งˆ๋ผ

  • null์„ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์€ ๋” ๋‚˜์˜๋‹ค.
  • ์•„๋ž˜ ์˜ˆ์ œ์— ๋ˆ„๊ตฐ๊ฐ€ null์„ ์ „๋‹ฌํ•œ๋‹ค๋ฉด, NullPointerException์ด ๋ฐœ์ƒํ•œ๋‹ค.
public class MetricsCalculator
{
    public double xProjection(Point p1, Point p2) {
        return (p2.x โ€“ p1.x) * 1.5;
    }
}

ํ•ด๊ฒฐ์ฑ… 1 : ์ƒˆ๋กœ์šด ์˜ˆ์™ธ ์œ ํ˜•์„ ๋งŒ๋“ค์–ด ๋˜์ง„๋‹ค.

public class MetricsCalculator
{
     public double xProjection(Point p1, Point p2) {
         if (p1 == null || p2 == null) {
             throw InvalidArgumentException(
                 "Invalid argument for MetricsCalculator.xProjection");
         }
         return (p2.x โ€“ p1.x) * 1.5;
     }
}
  • ํ•˜์ง€๋งŒ ์œ„ ์ฝ”๋“œ๋Š” InvalidArgumentException์„ ์žก์•„๋‚ด๋Š” ์ฒ˜๋ฆฌ๊ธฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

ํ•ด๊ฒฐ์ฒต 2 : assert ๋ฌธ์„ ์‚ฌ์šฉํ•œ๋‹ค.

public class MetricsCalculator
{
    public double xProjection(Point p1, Point p2) {
        assert p1 != null : "p1 should not be null";
        assert p2 != null : "p2 should not be null";
        return (p2.x โ€“ p1.x) * 1.5;
    }
}
  • ํ•˜์ง€๋งŒ ๋ˆ„๊ตฐ๊ฐ€ null์„ ์ „๋‹ฌํ•˜๋ฉด, ์—ฌ์ „ํžˆ ์‹คํ–‰์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
java.lang.AssertionError: p1 should not be null

๋Œ€๋‹ค์ˆ˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋Š” ํ˜ธ์ถœ์ž๊ฐ€ ์‹ค์ˆ˜๋กœ ๋„˜๊ธฐ๋Š” null์„ ์ ์ ˆํžˆ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์• ์ดˆ์— null์„ ๋„˜๊ธฐ์ง€ ๋ชปํ•˜๋„๋ก ๊ธˆ์ง€ํ•˜๋Š” ์ •์ฑ…์ด ํ•„์š”ํ•˜๋‹ค.


๊ฒฐ๋ก 

  • ๊นจ๋—ํ•œ ์ฝ”๋“œ๋Š” ์ฝ๊ธฐ๋„ ์ข‹์•„์•ผ ํ•˜์ง€๋งŒ ์•ˆ์ •์„ฑ๋„ ๋†’์•„์•ผ ํ•œ๋‹ค.
  • ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๋ฅผ ํ”„๋กœ๊ทธ๋žจ ๋…ผ๋ฆฌ์™€ ๋ถ„๋ฆฌํ•˜๋ฉด ๋…์ง‘์ ์ธ ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•ด์ง€๋ฉฐ ์ฝ”๋“œ ์œ ์ง€๋ณด์ˆ˜์„ฑ๋„ ๋†’์•„์ง„๋‹ค.