Clean Code Oop

[TOC]

OOP

์ฝ”๋“œ 1๊ฐœ์˜ ๋ผ์ธ์„ ๊ณ ์น˜๋ฉด 3๊ฐœ์˜ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์งค ๋•Œ ๊ณ„ํšํ•˜๊ณ  ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ์™€ ๊ทธ๋ ‡์ง€ ์•Š๊ณ  ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ๋Š” ์ˆ˜์ • ์‹œ๊ฐ„์€ ๋’ค๋กœ ๊ฐˆ์ˆ˜๋ก ์ฐจ์ด๊ฐ€ ๋‚œ๋‹ค.

SW๋Š” ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ์ตœ์†Œ 10๋ฒˆ ์ด์ƒ ์ฝํžŒ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด๋ฅผ ํ†ตํ•ด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ํ”„๋กœ๊ทธ๋žจ์ด ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์— ์ดˆ์ ์„ ๋งž์ถ”์ง€ ๋ง๊ณ  ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด โ€œ์ฝ๊ธฐโ€ ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์งœ๋Š”์ง€์— ์‹œ๊ฐ„์„ ํˆฌ์žํ•˜๊ณ  ๊ณ„ํšํ•ด์•ผํ•œ๋‹ค.

์™œ OOP์ผ๊นŒ?

image-20211010195437211

๋ฐ์ดํ„ฐ๊ฐ€ ํ•œ๊ณณ์— ๋ชจ์—ฌ์ ธ์žˆ๋Š”, ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ๊ณ  ์‘์ง‘๋„๊ฐ€ ๋†’์€ ์ฝ”๋“œ์ด๋‹ค. (์„ค๊ณ„X)

์ด๋Ÿฐ ์ฝ”๋“œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•ด์„œ ๊ธฐ์กด๊ฒƒ์„ ๋ณต์‚ฌ, ๋ถ™์—ฌ ๋„ฃ์„๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ์‹œ ์–ด๋””์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๊ณ  ์žˆ๋Š”์ง€ ์œ ์ง€, ๋ณด์ˆ˜๊ฐ€ ํž˜๋“ค๋‹ค

image-20211010195639629

๊ฐ ๊ฐ์ฒด๋งˆ๋‹ค ์˜์กด์„ฑ ์ฆ‰ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ ์กด์žฌ๋„ ๋ชจ๋ฅด๊ฒŒ ์ฝ”๋“œ๋ฅผ ์งœ๊ฒŒ ๋  ๊ฒฝ์šฐ ์ˆ˜์ •์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ ์†Œ์Šค๋ฅผ ์ „์ฒด์ ์œผ๋กœ ์ˆ˜์ •ํ•ด์•ผํ•˜๋Š” ๊ธฐ์กฑ์˜ ๋ฐฉ์‹๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ˆ˜์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๊ฐ€์žฅ ์ด์ƒ์ ์ธ ๊ฒฐํ•ฉ๋„๋Š” ๋†’๋„, ์‘์ง‘๋„๋Š” ๋‚ฎ์€ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

์ด์ƒ์ ์ธ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„๊ณผ์ •

์šฐ๋ฆฌ๊ฐ€ ์ถ”๊ตฌํ•ด์•ผ ํ•˜๋Š” ์„ค๊ณ„ ๋ฐฉํ–ฅ์€ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ํ•œ ๊ณณ์— ์ „๋ถ€ ๋„ฃ์–ด์„œ ๊ฐœ๋ฐœํ•˜๋Š” ์‹์˜ ๋ง‰์ฝ”๋”ฉ์ด ์•„๋‹ˆ๋ผ, ๊ฐ ๊ธฐ๋Šฅ๋งˆ๋‹ค ์ถ”์ถœ์„ ํ•ด์„œ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚˜์ถฐ์ฃผ๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณ ๊ฐ€๋ฉด์„œ ๋ฆฌํŽ™ํ† ๋ง์„ ํ•ด์•ผํ•œ๋‹ค.

๋ฌผ๋ก  ์ฒ˜์Œ๋ถ€ํ„ฐ, ์™„๋ฒฝํ•œ ์„ค๊ณ„๋ฅผ ํ•˜๋ฉด ์ข‹์ง€๋งŒ, ๋ฐฑ์ง€์—์„œ ์™„๋ฒฝํ•œ ํ”„๋กœ๊ทธ๋žจ ์„ค๊ณ„๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ฒƒ์€ ๋„ˆ๋ฌด ์–ด๋ ค์šด ์ผ์ด๋‹ค.

  1. ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ๊ฐ์ฒด ํ›„๋ณด ์„ ๋ณ„
    1. ๋‚ด๋ถ€์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ์„ ๋ณ„
    2. ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ
    3. ์ •์  ์„ค๊ณ„
  2. ์œ„์—์„œ ๋งŒ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํด๋ž˜์Šค๊ฐ„์— ๋ฉ”์‹œ์ง€ ํ๋ฆ„ ์—ฐ๊ฒฐ
    1. ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ ๋‹ค์ด์–ด๊ทธ๋žจ
    2. ์‹œํ€€์Šค ๋‹ค์ด์–ด๊ทธ๋žจ
    3. ๋™์  ์„ค๊ณ„

image-20211009204934803

์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ FlowController์— ๋ชจ๋“  ์—ญํ™œ์„ ์ง‘์–ด ๋„ฃ์ง€ ์•Š๊ณ  ๋ชจ๋‘ ๊ฐ ์—ญํ™œ๋งˆ๋‹ค ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.

์œ„์˜ ๊ทธ๋ฆผ์ด ์™„์„ฑ ๋์œผ๋ฉด, ์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์„ ๊ณ„ํšํ•œ๋‹ค.

์˜ˆ์‹œ์ฒ˜๋Ÿผ FlowController๋Š” ๊ฐ ์—ญํ™œ ๋ณ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด์ฃผ๋Š” ์—ญํ™œ์ด๋‹ค.

Encapsulation(์บก์Šํ™”)

๊ฐ์ฒด์ง€ํ–ฅ์—์„œ ๋Œ€ํ‘œ์ ์ธ ํŠน์„ฑ์ค‘์— ํ•˜๋‚˜์ธ ์บก์Šํ™”๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€๋ฅผ ๊ฐ์ถฐ์„œ ๋‚ด๋ถ€์˜ ๋ณ€๊ฒฝ(๋ฐ์ดํ„ฐ, ์ฝ”๋“œ)์ด Client๊ฐ€ ๋ณ€๊ฒฝ ๋˜์ง€ ์•Š๋„๋กํ•œ๋‹ค.

์ด๋Š” ์ฝ”๋“œ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ๋น„์šฉ์„ ์ตœ์†Œํ™” ์‹œ์ผœ์ค€๋‹ค.

์ ˆ์ฐจ์ง€ํ–ฅ์€ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ณ€๊ฒฝ ๋ ๋•Œ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ์˜ ๊ตฌ์กฐ๊ฐ€ ๋ณ€๊ฒฝ ๋˜์–ด์•ผํ•˜๊ณ  ์ด๋Š” ๋ชจ๋“  Client, Test์˜ ์ˆ˜์ •์ด ํ•„์š”ํ•ด ์ง€๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋–จ์–ด์ง„๋‹ค.

How? Tell! Donโ€™t ask!!

์บก์Šํ™”๊ฐ€ ์ž˜๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ž˜์•Œ๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฑฐ๊ณ  ๊ทธ ๊ฐ์ฒด์—๊ฒŒ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค. ์ง์ ‘์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•ด์„œ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ด ์•„๋‹Œ ์–ด๋–ป๊ฒŒ ์ •์˜ํ•˜๋ คํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

ex. If(member.getExpiredData().getTime() < System.currentTimeMillis){โ€ฆ}

if(member.isExpired()){โ€ฆ}

์ด๋Ÿฐ ์‹์œผ๋กœ ๋ช…๋ น๋งŒ ๋‚ด๋ฆฌ๊ฒŒ ๊ฐ์ฒด๋ฅผ ์ •์˜ ํ•ด์•ผํ•œ๋‹ค.

์˜ˆ์‹œ

package procedural;

import org.junit.Assert;
import org.junit.Test;

public class ProceduralStopWatchTest {
    private long expectedElapsedTime = 100l;

    @Test
    public void
    should_return_elapsed_milli_second() {
        ProceduralStopWatch stopWatch = new ProceduralStopWatch();

        stopWatch.startTime = System.currentTimeMillis(); // start time in millis

        doSomething();

        stopWatch.stopTime = System.currentTimeMillis(); // stop time in millis

        long elapsedTime = stopWatch.getElapsedTime();

        Assert.assertEquals(elapsedTime, expectedElapsedTime);
    }

    private void doSomething() {
        try {
            Thread.sleep(expectedElapsedTime);
        } catch (InterruptedException e) {
        }
    }
}
package procedural;

public class ProceduralStopWatch {
    public long startTime;
    public long stopTime;

    public long getElapsedTime() {
        return stopTime - startTime;
    }
}

์œ„ ์ฝ”๋“œ๋Š” ์‹œ์ž‘ ์‹œ๊ฐ„๋ถ€ํ„ฐ ๊ฒฝ๊ณผ๋œ ์‹œ๊ฐ„์„ ๊ตฌํ•˜๋Š” ์ ˆ์ฐจ์ง€ํ–ฅ์ ์ธ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

์—ฌ๊ธฐ์„œ ๋‚˜๋…ธ์„ธ์ปจ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด๋‹ฌ๋ผ๋Š” ์š”๊ตฌ์‚ฌํ•ญ์ด ๋“ค์–ด์™”๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ์ด ์ ˆ์ฐจ์ง€ํ–ฅ์ ์ธ ์ฝ”๋“œ์—์„œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€๋ฅผ ํ•ด์•ผํ•œ๋‹ค.

package procedural;

import org.junit.Assert;
import org.junit.Test;

public class ProceduralStopWatchTest {
    private long expectedElapsedTime = 100l;

    @Test
    public void
    should_return_elapsed_nano_seconds() {
        ProceduralStopWatch stopWatch = new ProceduralStopWatch();

        stopWatch.startNanoTime = System.nanoTime(); // start time in nanos

        doSomething();

        stopWatch.stopNanoTime = System.nanoTime(); // stop time in nanos

        long elapsedTime = stopWatch.getElapsedNanoTime();

        Assert.assertEquals(elapsedTime, expectedElapsedTime);
    }

    private void doSomething() {
        try {
            Thread.sleep(expectedElapsedTime);
        } catch (InterruptedException e) {
        }
    }
}
package procedural;

public class ProceduralStopWatch {
    public long startTime;
    public long stopTime;
    public long startNanoTime;
    public long stopNanoTime;

    public long getElapsedTime() {
        return stopTime - startTime;
    }

    public long getElapsedNanoTime() {
        return stopNanoTime - startNanoTime;
    }
}

์šฐ๋ฆฌ๊ฐ€ ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ ์ฝ”๋“œ์—์„œ ๋ด์•ผํ•  ๋ถ€๋ถ„์€ ์ ˆ์ฐจ์ง€ํ–ฅ์—์„œ ์ƒˆ๋กœ์šด ์š”๊ตฌ์‚ฌํ•ญ์ด ์ƒ๊ธฐ๋ฉด, ๊ฐœ๋ฐœ์ž๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์žฌ์ˆ˜์ •ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๊ธฐ์กด์— ์žˆ๋˜ ํ”„๋กœ๊ทธ๋žจ์€ ์‚ฌ๋ผ์ง€๊ณ  ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ์ด ์ƒ๊ฒผ๋‹ค. ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ํ”„๋กœ๊ทธ๋žจ์„ ์žฌ์‚ฌ์šฉ ์•Š๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ์ƒˆ๋กœ ๋งŒ๋“ค๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

package objective;

import org.junit.Assert;
import org.junit.Test;

public class ObjectiveStopWatchTest {
    private long expectedElapsedTime = 100l;

    @Test
    public void
    should_return_elapsed_millis() {
        ObjectiveStopWatch stopWatch = new ObjectiveStopWatch();
        stopWatch.start();

        doSomething();

        stopWatch.stop();

        Time time = stopWatch.getElapseTime();

        Assert.assertEquals(time.getMilliTime(), expectedElapsedTime);
    }

    private void doSomething() {
        try {
            Thread.sleep(expectedElapsedTime);
        } catch (InterruptedException e) {
        }
    }
}
package objective;

public class ObjectiveStopWatch {
    private long startTime;
    private long stopTime;

    public void start() {
        startTime = System.nanoTime();
    }

    public void stop() {
        stopTime = System.nanoTime();
    }

    public Time getElapseTime() {
        return new Time(stopTime - startTime);
    }
}
package objective;

public class Time {
    private long nano;

    public Time(long nano) {
        this.nano = nano;
    }

    public long getMilliTime() {
        return (long) (nano / Math.pow(10, 6));
    }
}

์œ„ ์ฝ”๋“œ๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์„ค๊ณ„๋กœ ๋งŒ๋“ค์–ด์ง„ ๊ฒฝ๊ณผ์‹œ๊ฐ„ ๊ตฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค. ์ดˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์ฃผ๋Š” Time์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ๋บ๋‹ค.

package objective;

import org.junit.Assert;
import org.junit.Test;

public class ObjectiveStopWatchTest {
    private long expectedElapsedTime = 100l;

    @Test
    public void
    should_return_elapsed_millis() {
        ObjectiveStopWatch stopWatch = new ObjectiveStopWatch();
        stopWatch.start();

        doSomething();

        stopWatch.stop();

        Time time = stopWatch.getElapseTime();

        Assert.assertEquals(time.getNanoTime(), expectedElapsedTime);
    }

    private void doSomething() {
        try {
            Thread.sleep(expectedElapsedTime);
        } catch (InterruptedException e) {
        }
    }
}
package objective;

public class Time {
    private long nano;

    public Time(long nano) {
        this.nano = nano;
    }

    public long getMilliTime() {
        return (long) (nano / Math.pow(10, 6));
    }

    public long getNanoTime() {
        return nano;
    }
}

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

๊ฐ์ฒด / ํด๋ž˜์Šค

์ข‹์€ ์ฝ”๋“œ๋Š” ๊ฐ ์—ญํ™œ์— ๋งž๊ฒŒ ์•Œ๋งž์€ ์ด๋ฆ„๊ณผ ์ด๋ฆ„์— ๋งž๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋Š” ์ด๋ฆ„์„ ์–ด๋–ป๊ฒŒ ์ง“๋Š๋ƒ์— ๋งŽ์€ ์‹œ๊ฐ„์„ ํˆฌ์ž ํ•ด์•ผํ•œ๋‹ค. ๊ฐ์ฒด, ํด๋ž˜์Šค๋Š” ์–ด๋–ป๊ฒŒ(How)๋กœ ์ •์˜ํ•˜์ง€ ์•Š๊ณ , ๋ฌด์—‡(What)์œผ๋กœ ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค. ๊ฐ์ฒด์™€ ํด๋ž˜์Šค๋Š” ์ฑ…์ž„์„ ๊ฐ€์ง€๋Š” ์—ญํ™œ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด SamsungSmartPhone์ด ์•„๋‹Œ SmartPhone์ด ๋˜์–ด์•ผ ํ•œ๊ณ , ๋„์„œ๊ด€ ์‚ฌ์„œ๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด, ์ฑ…๊ด€๋ฆฌ, ๋„์„œ๊ด€ ๊ด€๋ฆฌํ•˜๋Š” ์ฑ…์ž„์ด ์‚ฌ์„œ๋ผ๋Š” ์—ญํ™œ์— ์†ํ•ด ์žˆ๋‹ค.

  • Object
  • Role
  • Responsibility

Polymorphism(๋‹คํ˜•์„ฑ)

image-20211010211834663

ํ•œ ๊ฐ์ฒด๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€(poly) ๋ชจ์Šต(morph)์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

ZetMotorcycle zm = new ZetMotorcycle();
Motorcycle mc = zm;
ZetEngine ze = zm;

Zetmotorcycle ๊ฐ์ฒด๋Š” Motorcycle, ZetEngine ํด๋ž˜์Šค ์–ด๋Š ๋ชจ์Šต์ด๋“ ์ง€ ๊ฐ€์งˆ์ˆ˜๊ฐ€ ์žˆ๊ณ , Motorcycle์—์„œ๋Š” start(), ZetEngine์—์„œ๋Š” zetOn()๋ฅผ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

๋ณธ ๊ฐ•์ขŒ๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์—์„œ ๊ฐ€์žฅ ํฐ ํŠน์„ฑ์ธ ์žฌ์‚ฌ์šฉ์„ ์Šˆํผํด๋ž˜์„œ์—์„œ ์ƒ์†์„ ๋ฐ›์•„ ์žฌ์‚ฌ์šฉ ํ•˜๋Š” ๊ฒƒ์ด์•„๋‹Œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•ด์„œ ํ•ด์•ผํ•œ๋‹ค๊ณ  ๊ฐ•์กฐ ํ•œ๋‹ค.

์žฌ์‚ฌ์šฉ์ด๋ผ๋Š” ๊ฒƒ์€ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ ํ•  ๋•Œ ๊ธฐ์กด์— ์งœ๋†“์€ ๋กœ์ง์ด ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์œผ๋กœ ์ธํ•ด ๊ตฌํ˜„์ฒด์—์„œ๋Š” ๋ณ€๊ฒฝ์ด ๋ผ๋„, ๋ณ€๊ฒฝ์ด ๋˜์–ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

image-20211010213324289

์–ด๋Š ๊ฐ์ฒด์—์„œ๋“ ์ง€ Interface์˜ ๋กœ์ง์€ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” ์ƒ์„ธํ•œ ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ๋น ์ง€๋‹ค ๋ณด๋ฉด ์ƒ์œ„ ์ˆ˜์ค€์—์„œ์˜ ์„ค๊ณ„๋ฅผ ๋†“์น˜๊ธฐ ์‰ฝ์ง€๋งŒ, ์ถ”์ƒํ™”๋ฅผ ํ†ตํ•ด์„œ ์ƒ์œ„ ์ˆ˜์ค€์—์„œ์˜ ์„ค๊ณ„๋ฅผ ํ•˜๋Š”๋ฐ ๋„์›€์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

Abstract(์ƒ์†)

์ƒ์†์„ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋‹ค์ˆ˜์˜ ์„œ๋ธŒ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž, ๋งŒ์•ฝ ์ˆ˜ํผ ํด๋ž˜์Šค์—์„œ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚  ๊ฒฝ์šฐ ์ˆ˜ํผ ํด๋ž˜์Šค์—์„œ ์ƒ์†๋ฐ›์€ ๋‹ค์ˆ˜์˜ ์„œ๋ธŒ ํด๋ž˜์Šค์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.

์ž๋ฐ”์—์„œ๋Š” ๋‹ค์ค‘ ์ƒ์† ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ˆ˜ํผ ํด๋ž˜์Šค์— ์žˆ๋Š” ์ˆ˜๋งŽ์€ ๊ธฐ๋Šฅ ์ค‘์—์„œ ๋‹จ 1๊ฐ€์ง€๋งŒ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์„ ํƒ์ง€๋Š” 1๊ฐ€์ง€ ๊ธฐ๋Šฅ๋งŒ ์ƒ์†์„ ๋ฐ›๊ณ  ๋‹ค๋ฅธ ํ•œ๊ฐœ๋Š” ๊ตฌํ˜„ํ•˜๋Š” ์ˆ˜๋ฐ–์— ์—†๋‹ค. ์œ„ ์ƒํ™ฉ์—์„œ์˜ ๋ฌธ์ œ์ ์€ ์ด๋ฏธ ๋งŒ๋“ค์–ด๋†“์€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๊ณ  ์ƒˆ๋กœ ๋งŒ๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋Š˜์–ด๋‚œ๋‹ค.

package inheritance;

import java.util.ArrayList;

public class LuggageCompartment extends ArrayList<Luggage> {
    private int restSpace;

    public LuggageCompartment(int restSpace) {
        this.restSpace = restSpace;
    }

    @Override
    public boolean add(Luggage luggage) {
        this.restSpace -= luggage.getSize();
        super.add(luggage);
        return false;
    }

    public boolean canContain(Luggage luggage) {
        return this.restSpace > luggage.getSize();
    }

    public void extract(Luggage luggage) {
        this.restSpace += luggage.getSize();
        super.remove(luggage);
    }

}

์œ„ ํ”„๋กœ๊ทธ๋žจ์€ ์ˆ˜ํ™”๋ฌผ์„ ์ ์žฌํ•  ๋•Œ ์—ฌ์œ ๊ณต๊ฐ„์„ ์•Œ๋ ค์ฃผ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

๊ฐœ๋ฐœ์ž์˜ ์˜๋„๋Š” ์ˆ˜ํ™”๋ฌผ์„ ์ ์žฌํ•˜๋ฉด, ์—ฌ์œ ๊ณต๊ฐ„์€ ์ค„์–ด๋“ค๊ณ  ์ถœํ•˜ํ•˜๋ฉด, ์—ฌ์œ ๊ณต๊ฐ„์˜ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ๋Š” ์‹์ด๋‹ค.

package inheritance;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class LuggageCompartmentTest {
    private LuggageCompartment lc;

    @Before
    public void setUp() {
        lc = new LuggageCompartment(11);
    }

    @Test
    public void
    should_update_restSpace() {
        Luggage luggage = new Luggage(11, 10);

        if(lc.canContain(luggage)) {
            lc.add(luggage);
            Assert.assertEquals(lc.canContain(luggage), false);
        }

        lc.remove(luggage);
        Assert.assertEquals(lc.canContain(luggage), true);
    }
}

ํ•˜์ง€๋งŒ, ์œ„ ๊ฐœ๋ฐœ์ž์˜ ์˜๋„์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, extractํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉ์ง€ ์•Š๊ณ  ArrayList ํด๋ž˜์Šค์— ์žˆ๋Š” removeํ•จ์ˆ˜์— ๋ฐ”๋กœ ์ ‘๊ทผํ•˜์—ฌ ์ถœํ•˜๋ฅผ ํ•˜๋Š” ๋ฐ”๋žŒ์— ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์ด ๊นจ์ ธ๋ฒ„๋ฆฌ๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ๋‹ค.

๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ ์ฑ…์€ ArrayList๋ฅผ ์ƒ์† ๋ฐ›์ง€ ์•Š๊ณ , ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๋ฉด ์‚ฌ์šฉ์ž๋Š” ArrayList removeํ•จ์ˆ˜๋ฅผ ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•œ๋‹ค.

์ด๋Ÿฐ์‹์œผ๋กœ ๋ฌด์กฐ๊ฑด ์ƒ์†์„ ์“ฐ๋ฉด ์ข‹์€ ๊ฒƒ์ด ์•„๋‹Œ composition์„ ๋จผ์ €ํ•˜๊ณ  delegation์„ ํ•˜๋Š” ํ˜•์‹์˜ ํ”„๋กœ๊ทธ๋žจ์„ ์งœ๋ฉด ์œ ์—ฐ์„ฑ์ด ์ฆ๋Œ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜์— ์ ํ•ฉํ•œ ํ”„๋กœ๊ทธ๋žจ์ด ๋œ๋‹ค.

์ฐธ์กฐ

  • ๋ฐฑ๋ช…์„์˜ ํด๋ฆฐ์ฝ”๋“œ Youtube ๊ฐ•์ขŒ