์ค๋ฅ ํ๋๊ทธ๋ฅผ ์ค์ ํ๊ฑฐ๋, ํธ์ถ์์๊ฒ ์ค๋ฅ ์ฝ๋๋ฅผ ๋ฐํํ๋ ์์
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 ๋ธ๋ก์ผ๋ก ๋์ด๊ฐ ์ ์๋ค.
- try๋ธ๋ก์ ํธ๋์ญ์
๊ณผ ๋น์ทํ๋ค.
- try ๋ธ๋ก์์ ๋ฌด์จ ์ผ์ด ์๊ธฐ๋ catch ๋ธ๋ก์ ํ๋ก๊ทธ๋จ ์ํ๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ ์งํด์ผํ๋ค.
๋ฐ๋ผ์ ์์ธ๊ฐ ๋ฐ์ํ๋ ์ฝ๋๋ฅผ ์งค ๋ try-catch-finally๋ฌธ์ผ๋ก ์์ํ๋ ํธ์ด ์ข๋ค.
try๋ธ๋ก์์ ๋ฌด์จ ์ผ์ด ์๊ธฐ๋ , ํธ์ถ์๊ฐ ๊ธฐ๋ํ๋ ์ํ๋ฅผ ์ ์ํ๊ธฐ ์ฌ์์ง๋ค.
- ๊ฐ์ ๋ก ์์ธ๋ฅผ ์ผ์ผํค๋ ๋จ์ํ ์คํธ๋ฅผ ์์ฑํ๋ค.
@Test(expected = StorageException.class)
public void retrieveSectionShouldThrowOnInvalidFileName() {
sectionStore.retrieveSection("invalid - file");
}
- ๋จ์ํ ์คํธ์ ๋ง์ถฐ ๊ฐ๋จํ๊ฒ ์ฝ๋๋ฅผ ๊ตฌํํ๋ค.
public List<RecordedGrip> retrieveSection(String sectionName) {
// ์ค์ ๊ตฌํ์ ๊น์ง ๋๋ฏธ ๋ฐํ.
return new ArrayList<RecordedGrip>();
}
- ํ ์คํธ ์คํจ ํ ์ฑ๊ณตํ๋๋ก ๊ตฌํ์ ๋ณ๊ฒฝํ๋ค.
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>();
}
- ํ ์คํธ ์ฑ๊ณต ํ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ๋ค.
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๋ธ๋ก์ ํธ๋์ญ์ ๋ฒ์๋ถํฐ ๊ตฌํํ๊ฒ ๋๋ฏ๋ก ๋ฒ์ ๋ด์์ ํธ๋์ญ์ ๋ณธ์ง์ ์ ์งํ๊ธฐ ์ฌ์์ง๋ค.
- ๊ณผ๊ฑฐ์ ํ์ธ๋(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 ์๋ฐ)
์์ฃผ ์ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ฑํ๋ค๋ฉด, ๋ชจ๋ ์์ธ๋ฅผ ์ก๋๊ฒ ๋ง์ง๋ง ์ผ๋ฐ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์กด์ฑ์ด๋ผ๋ ๋น์ฉ์ด ์ด์ต๋ณด๋ค ํฌ๋ค
- 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 {
...
}
์ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ์ค๋ฅ ์ ํ๊ณผ ๋ฌด๊ดํ๊ฒ ์ผ์ ํ๋ค.
- ์ค๋ฅ ๊ธฐ๋ก
- ํ๋ก๊ทธ๋จ์ ๊ณ์ ์ํํด๋ ์ข์์ง ํ์ธ
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์ ๋ฐํํ๋ ์ต๊ด์ ์ค๋ฅ๋ฅผ ์ ๋ฐํ ์ ์๋ค.
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์ ์ ๋ฌํ๋ค๋ฉด, 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์ ๋๊ธฐ์ง ๋ชปํ๋๋ก ๊ธ์งํ๋ ์ ์ฑ ์ด ํ์ํ๋ค.
- ๊นจ๋ํ ์ฝ๋๋ ์ฝ๊ธฐ๋ ์ข์์ผ ํ์ง๋ง ์์ ์ฑ๋ ๋์์ผ ํ๋ค.
- ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ํ๋ก๊ทธ๋จ ๋ ผ๋ฆฌ์ ๋ถ๋ฆฌํ๋ฉด ๋ ์ง์ ์ธ ์ถ๋ก ์ด ๊ฐ๋ฅํด์ง๋ฉฐ ์ฝ๋ ์ ์ง๋ณด์์ฑ๋ ๋์์ง๋ค.