තවත් සමහරු වේලාසනින් විසි කළ යුත්තේ මන්දැයි සාරාංශ කොට ඇත. ඒ වෙනුවට ප්රමාද කොටස අල්ලා ගන්නේ ඇයිද යන්න පිළිබඳව අවධානය යොමු කිරීමට මට ඉඩ දෙන්න, ඒ සඳහා මගේ රසය පිළිබඳ තෘප්තිමත් පැහැදිලි කිරීමක් මා දැක නැත.
එසේ නම් ඇයි?
ව්යතිරේකයන් මුලින් පවතින්නේ මන්ද යන්න පිළිබඳව තරමක් ව්යාකූලත්වයක් ඇති බව පෙනේ. මෙහි විශාල රහස බෙදා ගැනීමට මට ඉඩ දෙන්න: ව්යතිරේකවලට හේතුව සහ ව්යතිරේකය හැසිරවීම ... උපුටා ගැනීම .
ඔබ මේ වගේ කේත දැක තිබේද:
static int divide(int dividend, int divisor) throws DivideByZeroException {
if (divisor == 0)
throw new DivideByZeroException(); // that's a checked exception indeed
return dividend / divisor;
}
static void doDivide() {
int a = readInt();
int b = readInt();
try {
int res = divide(a, b);
System.out.println(res);
} catch (DivideByZeroException e) {
// checked exception... I'm forced to handle it!
System.out.println("Nah, can't divide by zero. Try again.");
}
}
ව්යතිරේක භාවිතා කළ යුත්තේ එසේ නොවේ. ඉහත සඳහන් කේත සැබෑ ජීවිතයේ පවතී, නමුත් ඒවා බොහෝ දුරට අපගමනය වන අතර ඇත්ත වශයෙන්ම ව්යතිරේකය (pun) වේ. නිදසුනක් ලෙස බෙදීමේ අර්ථ දැක්වීම පිරිසිදු ගණිතයේ පවා කොන්දේසි සහිත ය: ආදාන වසම සීමා කිරීම සඳහා ශුන්යයේ සුවිශේෂී අවස්ථාව හැසිරවිය යුත්තේ “ඇමතුම් කේතය” ය. එය කැතයි. එය සැමවිටම අමතන්නාට වේදනාවකි. කෙසේ වෙතත්, එවැනි තත්වයන් සඳහා චෙක්-එවකට කළ යුතු රටාව යනු ස්වාභාවික මාර්ගයයි:
static int divide(int dividend, int divisor) {
// throws unchecked ArithmeticException for 0 divisor
return dividend / divisor;
}
static void doDivide() {
int a = readInt();
int b = readInt();
if (b != 0) {
int res = divide(a, b);
System.out.println(res);
} else {
System.out.println("Nah, can't divide by zero. Try again.");
}
}
විකල්පයක් ලෙස, ඔබට මේ ආකාරයට OOP ශෛලිය මත සම්පූර්ණ කමාන්ඩෝ යා හැකිය:
static class Division {
final int dividend;
final int divisor;
private Division(int dividend, int divisor) {
this.dividend = dividend;
this.divisor = divisor;
}
public boolean check() {
return divisor != 0;
}
public int eval() {
return dividend / divisor;
}
public static Division with(int dividend, int divisor) {
return new Division(dividend, divisor);
}
}
static void doDivide() {
int a = readInt();
int b = readInt();
Division d = Division.with(a, b);
if (d.check()) {
int res = d.eval();
System.out.println(res);
} else {
System.out.println("Nah, can't divide by zero. Try again.");
}
}
ඔබ දකින පරිදි, ඇමතුම් කේතය පෙර පරීක්ෂණයේ බර ඇති නමුත් පසුව කිසිදු ව්යතිරේකයක් හැසිරවීමක් නොකරයි. ArithmeticException
කවදා divide
හෝ ඇමතුමක් ලැබෙන්නේ නම් හෝ eval
, එවිට ඔබට ව්යතිරේකය හැසිරවිය යුතු අතර ඔබේ කේතය නිවැරදි කළ check()
යුතුය. ඒ හා සමාන හේතූන් මත අල්ලා ගැනීම NullPointerException
සැමවිටම පාහේ වැරදි දෙයකි.
දැන් සමහර පුද්ගලයින් ක්රමයේ / ක්රියාකාරී අත්සනෙහි සුවිශේෂී අවස්ථා දැකීමට අවශ්ය යැයි පවසන අය සිටිති, එනම් ප්රතිදාන වසම පැහැදිලිව දීර් extend කිරීම . පරීක්ෂා කළ ව්යතිරේකයන්ට කැමති අය ඔවුන් ය . ඇත්ත වශයෙන්ම, ප්රතිදාන වසම වෙනස් කිරීම ඕනෑම සෘජු ඇමතුම් කේතයක් අනුවර්තනය වීමට බල කළ යුතු අතර, එය සැබවින්ම පරික්ෂා කළ ව්යතිරේකයන් සමඟ සාක්ෂාත් කර ගනු ඇත. නමුත් ඒ සඳහා ඔබට ව්යතිරේක අවශ්ය නොවේ! ඔබට Nullable<T>
සාමාන්ය පන්ති , සිද්ධි පන්ති , වීජීය දත්ත වර්ග සහ වෘත්තීය සමිති වර්ග ඇත්තේ එබැවිනි . සමහර OO පුද්ගලයින් මෙවැනි සරල වැරදි අවස්ථා සඳහා නැවත පැමිණීමට කැමති විය හැකිය null
:
static Integer divide(int dividend, int divisor) {
if (divisor == 0) return null;
return dividend / divisor;
}
static void doDivide() {
int a = readInt();
int b = readInt();
Integer res = divide(a, b);
if (res != null) {
System.out.println(res);
} else {
System.out.println("Nah, can't divide by zero. Try again.");
}
}
ඉහත සඳහන් අරමුණු සඳහා තාක්ෂණික ව්යතිරේක භාවිතා කළ හැකි නමුත් මෙහි කාරණය මෙයයි: එවැනි භාවිතය සඳහා ව්යතිරේකයන් නොපවතී . ව්යතිරේකයන් යනු ගැති සාරාංශයකි. ව්යතිරේකය යනු අවිනිශ්චිතතාවයයි. ව්යතිරේකයන් මඟින් සෘජු සේවාදායක ගිවිසුම් කඩ නොකර " ප්රති come ල " වසම දීර් extend කිරීමට සහ දෝෂ හැසිරවීම "වෙනත් තැනකට" කල් දැමීමට ඉඩ දෙයි . ඔබේ කේතය එකම කේතයේ සෘජු අමතන්නන් විසින් හසුරුවනු ලබන ව්යතිරේකයන් විසි කරන්නේ නම්, අතර කිසිදු සාරාංශයක් නොමැතිව, ඔබ එය කරන්නේ වැරදියි
ප්රමාද වන්නේ කෙසේද?
ඉතින් මෙන්න අපි. ඉහත අවස්ථා වලදී ව්යතිරේක භාවිතා කිරීම යනු ව්යතිරේක භාවිතා කළ යුතු ආකාරය නොවන බව පෙන්වීමට මම මගේ මාර්ගය තර්ක කර ඇත්තෙමි. ව්යතිරේකය හැසිරවීම මගින් ඉදිරිපත් කරන වියුක්ත කිරීම සහ නිරවද්යතාවය අත්යවශ්ය වන අව්යාජ භාවිත නඩුවක් පවතී. එවැනි භාවිතය අවබෝධ කර ගැනීම ප්රමාද වූ නිර්දේශය තේරුම් ගැනීමට උපකාරී වේ.
එම භාවිත අවස්ථාව මෙයයි: සම්පත් සාරාංශවලට එරෙහිව වැඩසටහන්කරණය ...
ඔව්, ව්යාපාර තර්කනය ක්රමලේඛනය කළ යුත්තේ වියුක්තයන්ට එරෙහිව මිස ස්ථිර ලෙස ක්රියාත්මක කිරීමට නොවේ. ඉහළ මට්ටමේ IOC "රැහැන්" කේතය මඟින් සම්පත් වියුක්ත කිරීම් ස්ථිර ලෙස ක්රියාත්මක කිරීම ක්ෂණිකව ක්රියාත්මක වන අතර ඒවා ව්යාපාර තර්කනයට යොමු කරයි. මෙහි අලුත් දෙයක් නැත. එහෙත් එම සම්පත් සාරාංශවල සංයුක්ත ක්රියාවට නැංවීම ඔවුන්ගේම ක්රියාත්මක කිරීමේ විශේෂිත ව්යතිරේකයන් විසි කිරීමට ඉඩ තිබේ.
එම ක්රියාත්මක කිරීමේ විශේෂිත ව්යතිරේකයන් හැසිරවිය හැක්කේ කාටද? එවිට ව්යාපාර තර්කනයේ කිසියම් සම්පත් විශේෂිත ව්යතිරේකයක් හැසිරවිය හැකිද? නැහැ, එසේ නොවේ. ව්යාපාර තර්කනය වියුක්තකරණයට එරෙහිව වැඩසටහන්ගත කර ඇති අතර එමඟින් එම ක්රියාත්මක කිරීමේ විශේෂිත ව්යතිරේක තොරතුරු පිළිබඳ දැනුම බැහැර කරනු ලැබේ.
"ආහා!", ඔබට මෙසේ පැවසිය හැකිය: "නමුත් අපට ව්යතිරේකයන් උප වර්ගීකරණය කර ව්යතිරේක ධූරාවලියක් නිර්මාණය කළ හැක්කේ එබැවිනි" ( ස්ප්රිං මහතා බලන්න!). මම ඔබට කියන්නම්, එය වැරැද්දකි. පළමුවෙන්ම, ඕඕපී පිළිබඳ සෑම සාධාරණ පොතක්ම පවසන්නේ කොන්ක්රීට් උරුමය නරක බවය, නමුත් කෙසේ හෝ ජේවීඑම් හි මෙම මූලික අංගය, ව්යතිරේකය හැසිරවීම කොන්ක්රීට් උරුමය සමඟ සමීපව බැඳී ඇත. උත්ප්රාසාත්මක ලෙස, වැඩ කරන ජේවීඑම් සමඟ අත්දැකීම් ලබා ගැනීමට පෙර ජෝෂුවා බ්ලොච්ට ඔහුගේ Java ලදායී ජාවා පොත ලිවීමට නොහැකි විය. එය ඊළඟ පරම්පරාවට "උගත් පාඩම්" පොතකි. දෙවනුව, සහ වඩා වැදගත් දෙය නම්, ඔබ ඉහළ මට්ටමේ ව්යතිරේකයක් අල්ලා ගන්නේ නම් ඔබ එය හසුරුවන්නේ කෙසේද?PatientNeedsImmediateAttentionException
: අපි ඇයට බෙහෙත් පෙත්තක් දිය යුතුද? නැතහොත් ඇගේ කකුල් කපා දැමිය යුතුද? හැකි සියලුම උප පංති හරහා ස්විච් ප්රකාශයක් කරන්නේ කෙසේද? ඔබේ බහුමාපකය එහි යයි, වියුක්තය පවතී. ඔබට කාරණය තේරුණා.
සම්පත් නිශ්චිත ව්යතිරේක හැසිරවිය හැක්කේ කාටද? එය කොන්ක්රීට් දන්නා තැනැත්තා විය යුතුය! සම්පත ක්ෂණික කළ තැනැත්තා! ඇත්ත වශයෙන්ම "රැහැන්" කේතය! මෙය පරීක්ෂා කරන්න:
ව්යාපාර තර්කනය වියුක්ත කිරීමට එරෙහිව කේතනය කර ඇත ... සම්පූර්ණ සම්පත් දෝෂයක් නැත!
static interface InputResource {
String fetchData();
}
static interface OutputResource {
void writeData(String data);
}
static void doMyBusiness(InputResource in, OutputResource out, int times) {
for (int i = 0; i < times; i++) {
System.out.println("fetching data");
String data = in.fetchData();
System.out.println("outputting data");
out.writeData(data);
}
}
මේ අතර වෙනත් තැනක සංයුක්ත ක්රියාත්මක කිරීම් ...
static class ConstantInputResource implements InputResource {
@Override
public String fetchData() {
return "Hello World!";
}
}
static class FailingInputResourceException extends RuntimeException {
public FailingInputResourceException(String message) {
super(message);
}
}
static class FailingInputResource implements InputResource {
@Override
public String fetchData() {
throw new FailingInputResourceException("I am a complete failure!");
}
}
static class StandardOutputResource implements OutputResource {
@Override
public void writeData(String data) {
System.out.println("DATA: " + data);
}
}
අවසාන වශයෙන් රැහැන් කේතය ... කොන්ක්රීට් සම්පත් ව්යතිරේකයන් හසුරුවන්නේ කවුද? ඔවුන් ගැන දන්නා තැනැත්තා!
static void start() {
InputResource in1 = new FailingInputResource();
InputResource in2 = new ConstantInputResource();
OutputResource out = new StandardOutputResource();
try {
ReusableBusinessLogicClass.doMyBusiness(in1, out, 3);
}
catch (FailingInputResourceException e)
{
System.out.println(e.getMessage());
System.out.println("retrying...");
ReusableBusinessLogicClass.doMyBusiness(in2, out, 3);
}
}
දැන් මා සමඟ ඉවසන්න. ඉහත කේතය වන්නේ සරල. ඔබට IOC බහාලුම් කළමණාකරන සම්පත් වල විවිධ විෂය පථයන් සහිත ව්යවසාය යෙදුමක් / වෙබ් බහාලුමක් ඇති බව ඔබට පැවසිය හැකිය, ඔබට ස්වයංක්රීයව නැවත උත්සාහ කිරීම සහ සැසිය නැවත ආරම්භ කිරීම හෝ විෂය පථ සම්පත් ඉල්ලීම යනාදිය අවශ්ය වේ. පහළ මට්ටමේ විෂය පථයන්හි රැහැන් තර්කනයට වියුක්ත කර්මාන්තශාලා ලබා දිය හැකිය. සම්පත් නිර්මාණය කිරීම, එබැවින් නිශ්චිත ක්රියාත්මක කිරීම් පිළිබඳව නොදැන සිටීම. පහළ මට්ටමේ සම්පත් වලට විසි කළ හැකි ව්යතිරේකයන් මොනවාදැයි දැනගත හැක්කේ ඉහළ මට්ටමේ විෂය පථයන්ට පමණි. දැන් ඉන්න!
අවාසනාවකට මෙන්, ව්යතිරේකයන් මඟින් ඇමතුම් තොගයට ඉහළින් ගමන් කිරීමට පමණක් ඉඩ ලබා දෙන අතර, ඒවායේ විවිධ කාදිනල්තා සහිත විවිධ විෂය පථයන් සාමාන්යයෙන් විවිධ නූල් මත ධාවනය වේ. ව්යතිරේකයන් සමඟ ඒ හරහා සන්නිවේදනය කිරීමට ක්රමයක් නොමැත. අපට මෙහි වඩා බලවත් දෙයක් අවශ්යයි. පිළිතුර: අසමකාලීක පණිවිඩය සම්මත . සෑම ව්යතිරේකයක්ම පහළ මට්ටමේ විෂය පථයේ මුල අල්ලා ගන්න. කිසිවක් නොසලකා හරින්න, කිසිවක් ලිස්සා යාමට ඉඩ නොදෙන්න. මෙය වත්මන් විෂය පථයේ ඇමතුම් තොගයේ ඇති සියලුම සම්පත් වසා දමා බැහැර කරනු ඇත. ඔබ කොන්ක්රීට් දන්නා මට්ටමට ළඟා වන තුරු, ව්යතිරේක හැසිරවීමේ චර්යාවේ පණිවුඩ පෝලිම් / නාලිකා භාවිතා කිරීමෙන් දෝෂ පණිවිඩ ඉහළට ගෙන යන්න. එය හැසිරවිය යුතු ආකාරය දන්නා පුද්ගලයා එයයි.
සුමා සුමාරම්
එබැවින් මගේ අර්ථ නිරූපණයට අනුව ප්රමාදයන් අල්ලා ගැනීම වඩාත් පහසු ස්ථානයක ව්යතිරේකයන් අල්ලා ගැනීම ඔබ කොතැනකවත් නොපැමිණියේ කොතැනද ? වේලාසනින් අල්ලා නොගන්න! ඔබ කොන්ක්රීට් ව්යතිරේකය නිර්මාණය කරන ස්ථරයේ ව්යතිරේකයන් අල්ලා ගන්න, සම්පත් වියුක්ත කිරීම්, වියුක්තයන්ගේ කොන්ක්රීට් දන්නා ස්තරය . "රැහැන්" ස්ථරය.
HTH. සුබ කේතීකරණයක්!