ಪೈಥಾನ್ನ ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಬೇಸ್ ಕ್ಲಾಸ್ಗಳ (ABCs) ಶಕ್ತಿಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ. ಪ್ರೋಟೋಕಾಲ್-ಆಧಾರಿತ ಸ್ಟ್ರಕ್ಚರಲ್ ಟೈಪಿಂಗ್ ಮತ್ತು ಫಾರ್ಮಲ್ ಇಂಟರ್ಫೇಸ್ ವಿನ್ಯಾಸದ ನಡುವಿನ ಪ್ರಮುಖ ವ್ಯತ್ಯಾಸವನ್ನು ತಿಳಿಯಿರಿ.
ಪೈಥಾನ್ ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಬೇಸ್ ಕ್ಲಾಸ್ಗಳು: ಪ್ರೋಟೋಕಾಲ್ ಇಂಪ್ಲಿಮೆಂಟೇಶನ್ ಮತ್ತು ಇಂಟರ್ಫೇಸ್ ವಿನ್ಯಾಸದ ನಡುವಿನ ಪಾಂಡಿತ್ಯ
ಸಾಫ್ಟ್ವೇರ್ ಅಭಿವೃದ್ಧಿ ಜಗತ್ತಿನಲ್ಲಿ, ದೃಢವಾದ, ನಿರ್ವಹಿಸಬಹುದಾದ ಮತ್ತು ವಿಸ್ತರಿಸಬಹುದಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ನಿರ್ಮಿಸುವುದು ಅಂತಿಮ ಗುರಿಯಾಗಿದೆ. ಯೋಜನೆಗಳು ಕೆಲವು ಸ್ಕ್ರಿಪ್ಟ್ಗಳಿಂದ ಹಿಡಿದು ಅಂತರರಾಷ್ಟ್ರೀಯ ತಂಡಗಳಿಂದ ನಿರ್ವಹಿಸಲ್ಪಡುವ ಸಂಕೀರ್ಣ ವ್ಯವಸ್ಥೆಗಳಾಗಿ ಬೆಳೆದಂತೆ, ಸ್ಪಷ್ಟವಾದ ರಚನೆ ಮತ್ತು ನಿರೀಕ್ಷಿತ ಒಪ್ಪಂದಗಳ ಅವಶ್ಯಕತೆ ಹೆಚ್ಚಾಗುತ್ತದೆ. ವಿವಿಧ ಸಮಯ ವಲಯಗಳಲ್ಲಿ, ವಿವಿಧ ಡೆವಲಪರ್ಗಳಿಂದ ಬರೆಯಲ್ಪಟ್ಟಿರಬಹುದಾದ ವಿಭಿನ್ನ ಘಟಕಗಳು ಯಾವುದೇ ಅಡೆತಡೆಯಿಲ್ಲದೆ ಮತ್ತು ವಿಶ್ವಾಸಾರ್ಹವಾಗಿ ಸಂವಹನ ನಡೆಸಬಹುದೆಂದು ನಾವು ಹೇಗೆ ಖಚಿತಪಡಿಸಿಕೊಳ್ಳುತ್ತೇವೆ? ಉತ್ತರವು ಅಬ್ಸ್ಟ್ರಾಕ್ಷನ್ (abstraction) ತತ್ವದಲ್ಲಿದೆ.
ಪೈಥಾನ್, ತನ್ನ ಡೈನಾಮಿಕ್ ಸ್ವಭಾವದೊಂದಿಗೆ, ಅಬ್ಸ್ಟ್ರಾಕ್ಷನ್ಗಾಗಿ ಒಂದು ಪ್ರಸಿದ್ಧ ತತ್ವವನ್ನು ಹೊಂದಿದೆ: "ಡಕ್ ಟೈಪಿಂಗ್". ಒಂದು ವಸ್ತುವು ಬಾತುಕೋಳಿಯಂತೆ ನಡೆದರೆ ಮತ್ತು ಬಾತುಕೋಳಿಯಂತೆ ಕೂಗಿದರೆ, ನಾವು ಅದನ್ನು ಬಾತುಕೋಳಿಯಂತೆಯೇ ಪರಿಗಣಿಸುತ್ತೇವೆ. ಈ ನಮ್ಯತೆಯು ಪೈಥಾನ್ನ ಅತಿ ದೊಡ್ಡ ಶಕ್ತಿಗಳಲ್ಲಿ ಒಂದಾಗಿದೆ, ಇದು ವೇಗದ ಅಭಿವೃದ್ಧಿ ಮತ್ತು ಸ್ವಚ್ಛ, ಓದಬಲ್ಲ ಕೋಡ್ಗೆ ಪ್ರೋತ್ಸಾಹ ನೀಡುತ್ತದೆ. ಆದಾಗ್ಯೂ, ದೊಡ್ಡ ಪ್ರಮಾಣದ ಅಪ್ಲಿಕೇಶನ್ಗಳಲ್ಲಿ, ಕೇವಲ ಸೂಚ್ಯ ಒಪ್ಪಂದಗಳ ಮೇಲೆ ಅವಲಂಬಿತರಾಗುವುದು ಸೂಕ್ಷ್ಮ ದೋಷಗಳಿಗೆ ಮತ್ತು ನಿರ್ವಹಣೆಯ ತಲೆನೋವಿಗೆ ಕಾರಣವಾಗಬಹುದು. ಒಂದು 'ಬಾತುಕೋಳಿ' ಅನಿರೀಕ್ಷಿತವಾಗಿ ಹಾರಲು ಸಾಧ್ಯವಾಗದಿದ್ದಾಗ ಏನಾಗುತ್ತದೆ? ಇಲ್ಲಿಯೇ ಪೈಥಾನ್ನ ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಬೇಸ್ ಕ್ಲಾಸ್ಗಳು (ABCs) ರಂಗಪ್ರವೇಶಿಸುತ್ತವೆ, ಪೈಥಾನ್ನ ಡೈನಾಮಿಕ್ ಸ್ಪಿರಿಟ್ಗೆ ಧಕ್ಕೆಯಾಗದಂತೆ ಔಪಚಾರಿಕ ಒಪ್ಪಂದಗಳನ್ನು ರಚಿಸಲು ಪ್ರಬಲ ಯಾಂತ್ರಿಕತೆಯನ್ನು ಒದಗಿಸುತ್ತವೆ.
ಆದರೆ ಇಲ್ಲಿ ಒಂದು ನಿರ್ಣಾಯಕ ಮತ್ತು ಆಗಾಗ್ಗೆ ತಪ್ಪಾಗಿ ಅರ್ಥೈಸಿಕೊಳ್ಳುವ ವ್ಯತ್ಯಾಸವಿದೆ. ಪೈಥಾನ್ನಲ್ಲಿ ಎಬಿಸಿಗಳು (ABCs) ಒಂದೇ ಗಾತ್ರಕ್ಕೆ ಸರಿಹೊಂದುವ ಸಾಧನವಲ್ಲ. ಅವು ಸಾಫ್ಟ್ವೇರ್ ವಿನ್ಯಾಸದ ಎರಡು ವಿಭಿನ್ನ, ಶಕ್ತಿಶಾಲಿ ತತ್ವಗಳನ್ನು ಪೂರೈಸುತ್ತವೆ: ಸ್ಪಷ್ಟ, ಔಪಚಾರಿಕ ಇಂಟರ್ಫೇಸ್ಗಳನ್ನು ರಚಿಸುವುದು, ಅದು ಇನ್ಹೆರಿಟೆನ್ಸ್ (inheritance) ಅನ್ನು ಬಯಸುತ್ತದೆ ಮತ್ತು ನಮ್ಯವಾದ ಪ್ರೋಟೋಕಾಲ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸುವುದು, ಅದು ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಪರಿಶೀಲಿಸುತ್ತದೆ. ಈ ಎರಡು ವಿಧಾನಗಳ ನಡುವಿನ ವ್ಯತ್ಯಾಸವನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು - ಇಂಟರ್ಫೇಸ್ ವಿನ್ಯಾಸ ಮತ್ತು ಪ್ರೋಟೋಕಾಲ್ ಇಂಪ್ಲಿಮೆಂಟೇಶನ್ - ಪೈಥಾನ್ನಲ್ಲಿ ಆಬ್ಜೆಕ್ಟ್-ಓರಿಯೆಂಟೆಡ್ ವಿನ್ಯಾಸದ ಸಂಪೂರ್ಣ ಸಾಮರ್ಥ್ಯವನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಲು ಮತ್ತು ನಮ್ಯ ಹಾಗೂ ಸುರಕ್ಷಿತವಾಗಿರುವ ಕೋಡ್ ಬರೆಯಲು ಪ್ರಮುಖವಾಗಿದೆ. ಈ ಮಾರ್ಗದರ್ಶಿಯು ಎರಡೂ ತತ್ವಗಳನ್ನು ಅನ್ವೇಷಿಸುತ್ತದೆ, ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳನ್ನು ಮತ್ತು ನಿಮ್ಮ ಜಾಗತಿಕ ಸಾಫ್ಟ್ವೇರ್ ಯೋಜನೆಗಳಲ್ಲಿ ಪ್ರತಿಯೊಂದು ವಿಧಾನವನ್ನು ಯಾವಾಗ ಬಳಸಬೇಕೆಂಬುದರ ಬಗ್ಗೆ ಸ್ಪಷ್ಟ ಮಾರ್ಗದರ್ಶನ ನೀಡುತ್ತದೆ.
ಫಾರ್ಮ್ಯಾಟಿಂಗ್ ಕುರಿತು ಒಂದು ಟಿಪ್ಪಣಿ: ನಿರ್ದಿಷ್ಟ ಫಾರ್ಮ್ಯಾಟಿಂಗ್ ನಿರ್ಬಂಧಗಳನ್ನು ಪಾಲಿಸಲು, ಈ ಲೇಖನದಲ್ಲಿನ ಕೋಡ್ ಉದಾಹರಣೆಗಳನ್ನು ಬೋಲ್ಡ್ ಮತ್ತು ಇಟಾಲಿಕ್ ಶೈಲಿಗಳನ್ನು ಬಳಸಿಕೊಂಡು ಸ್ಟ್ಯಾಂಡರ್ಡ್ ಟೆಕ್ಸ್ಟ್ ಟ್ಯಾಗ್ಗಳಲ್ಲಿ ಪ್ರಸ್ತುತಪಡಿಸಲಾಗಿದೆ. ಉತ್ತಮ ಓದುವಿಕೆಗಾಗಿ ಅವುಗಳನ್ನು ನಿಮ್ಮ ಎಡಿಟರ್ಗೆ ನಕಲಿಸಲು ನಾವು ಶಿಫಾರಸು ಮಾಡುತ್ತೇವೆ.
ಅಡಿಪಾಯ: ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಬೇಸ್ ಕ್ಲಾಸ್ಗಳು ಎಂದರೆ ನಿಖರವಾಗಿ ಏನು?
ಎರಡು ವಿನ್ಯಾಸ ತತ್ವಗಳ ಬಗ್ಗೆ ತಿಳಿದುಕೊಳ್ಳುವ ಮೊದಲು, ನಾವು ಒಂದು ದೃಢವಾದ ಅಡಿಪಾಯವನ್ನು ಸ್ಥಾಪಿಸೋಣ. ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಬೇಸ್ ಕ್ಲಾಸ್ ಎಂದರೇನು? ಮೂಲಭೂತವಾಗಿ, ಎಬಿಸಿ (ABC) ಎನ್ನುವುದು ಇತರ ಕ್ಲಾಸ್ಗಳಿಗೆ ಒಂದು ಬ್ಲೂಪ್ರಿಂಟ್ (blueprint). ಇದು ಒಂದು ಕ್ಲಾಸ್ ಅನುಸರಿಸಬೇಕಾದ ಮೆಥಡ್ಗಳು ಮತ್ತು ಪ್ರಾಪರ್ಟಿಗಳ ಗುಂಪನ್ನು ವ್ಯಾಖ್ಯಾನಿಸುತ್ತದೆ. "ಈ ಕುಟುಂಬದ ಭಾಗವೆಂದು ಹೇಳಿಕೊಳ್ಳುವ ಯಾವುದೇ ಕ್ಲಾಸ್ ಈ ನಿರ್ದಿಷ್ಟ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಹೊಂದಿರಬೇಕು" ಎಂದು ಹೇಳುವ ಒಂದು ವಿಧಾನವಿದು.
ಪೈಥಾನ್ನ ಅಂತರ್ನಿರ್ಮಿತ `abc` ಮಾಡ್ಯೂಲ್ ಎಬಿಸಿಗಳನ್ನು ರಚಿಸಲು ಬೇಕಾದ ಸಾಧನಗಳನ್ನು ಒದಗಿಸುತ್ತದೆ. ಇದರ ಎರಡು ಪ್ರಮುಖ ಘಟಕಗಳೆಂದರೆ:
- `ABC`: ಎಬಿಸಿ ರಚಿಸಲು ಮೆಟಾಕ್ಲಾಸ್ ಆಗಿ ಬಳಸಲಾಗುವ ಸಹಾಯಕ ಕ್ಲಾಸ್. ಆಧುನಿಕ ಪೈಥಾನ್ನಲ್ಲಿ (3.4+), ನೀವು ಸರಳವಾಗಿ `abc.ABC` ನಿಂದ ಇನ್ಹೆರಿಟ್ ಮಾಡಬಹುದು.
- `@abstractmethod`: ಮೆಥಡ್ಗಳನ್ನು ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಎಂದು ಗುರುತಿಸಲು ಬಳಸುವ ಡೆಕೋರೇಟರ್. ಎಬಿಸಿಯ ಯಾವುದೇ ಸಬ್ಕ್ಲಾಸ್ ಈ ಮೆಥಡ್ಗಳನ್ನು ಇಂಪ್ಲಿಮೆಂಟ್ ಮಾಡಲೇಬೇಕು.
ಎಬಿಸಿಗಳನ್ನು ನಿಯಂತ್ರಿಸುವ ಎರಡು ಮೂಲಭೂತ ನಿಯಮಗಳಿವೆ:
- ನೀವು ಇಂಪ್ಲಿಮೆಂಟ್ ಮಾಡದ ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಮೆಥಡ್ಗಳಿರುವ ಎಬಿಸಿಯ ಇನ್ಸ್ಟೆನ್ಸ್ (instance) ಅನ್ನು ರಚಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಇದೊಂದು ಟೆಂಪ್ಲೇಟ್, ಪೂರ್ಣಗೊಂಡ ಉತ್ಪನ್ನವಲ್ಲ.
- ಯಾವುದೇ ಕಾಂಕ್ರೀಟ್ ಸಬ್ಕ್ಲಾಸ್ ಇನ್ಹೆರಿಟ್ ಮಾಡಿದ ಎಲ್ಲಾ ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಮೆಥಡ್ಗಳನ್ನು ಇಂಪ್ಲಿಮೆಂಟ್ ಮಾಡಬೇಕು. ಹಾಗೆ ಮಾಡಲು ವಿಫಲವಾದರೆ, ಅದೂ ಕೂಡ ಒಂದು ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಕ್ಲಾಸ್ ಆಗುತ್ತದೆ, ಮತ್ತು ನೀವು ಅದರ ಇನ್ಸ್ಟೆನ್ಸ್ ಅನ್ನು ರಚಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ.
ಇದನ್ನು ಒಂದು ಕ್ಲಾಸಿಕ್ ಉದಾಹರಣೆಯೊಂದಿಗೆ ನೋಡೋಣ: ಮೀಡಿಯಾ ಫೈಲ್ಗಳನ್ನು ನಿರ್ವಹಿಸುವ ವ್ಯವಸ್ಥೆ.
ಉದಾಹರಣೆ: ಒಂದು ಸರಳ MediaFile ABC
ನಾವು ವಿವಿಧ ರೀತಿಯ ಮೀಡಿಯಾವನ್ನು ನಿರ್ವಹಿಸಬೇಕಾದ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ನಿರ್ಮಿಸುತ್ತಿದ್ದೇವೆ ಎಂದು ಊಹಿಸಿ. ಯಾವುದೇ ಮೀಡಿಯಾ ಫೈಲ್, ಅದರ ಫಾರ್ಮ್ಯಾಟ್ ಏನೇ ಇರಲಿ, ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಾಗಬೇಕು ಮತ್ತು ಕೆಲವು ಮೆಟಾಡೇಟಾವನ್ನು ಹೊಂದಿರಬೇಕು ಎಂದು ನಮಗೆ ತಿಳಿದಿದೆ. ನಾವು ಈ ಒಪ್ಪಂದವನ್ನು ಎಬಿಸಿ ಬಳಸಿ ವ್ಯಾಖ್ಯಾನಿಸಬಹುದು.
import abc
class MediaFile(abc.ABC):
def __init__(self, filepath: str):
self.filepath = filepath
print(f"Base init for {self.filepath}")
@abc.abstractmethod
def play(self) -> None:
"""Play the media file."""
raise NotImplementedError
@abc.abstractmethod
def get_metadata(self) -> dict:
"""Return a dictionary of media metadata."""
raise NotImplementedError
ನಾವು ನೇರವಾಗಿ `MediaFile` ನ ಇನ್ಸ್ಟೆನ್ಸ್ ಅನ್ನು ರಚಿಸಲು ಪ್ರಯತ್ನಿಸಿದರೆ, ಪೈಥಾನ್ ನಮ್ಮನ್ನು ತಡೆಯುತ್ತದೆ:
# ಇದು TypeError ಅನ್ನು ರೈಸ್ ಮಾಡುತ್ತದೆ
# media = MediaFile("path/to/somefile.txt")
# TypeError: Can't instantiate abstract class MediaFile with abstract methods get_metadata, play
ಈ ಬ್ಲೂಪ್ರಿಂಟ್ ಬಳಸಲು, ನಾವು `play()` ಮತ್ತು `get_metadata()` ಗಾಗಿ ಇಂಪ್ಲಿಮೆಂಟೇಶನ್ಗಳನ್ನು ಒದಗಿಸುವ ಕಾಂಕ್ರೀಟ್ ಸಬ್ಕ್ಲಾಸ್ಗಳನ್ನು ರಚಿಸಬೇಕು.
class AudioFile(MediaFile):
def play(self) -> None:
print(f"Playing audio from {self.filepath}...")
def get_metadata(self) -> dict:
return {"codec": "mp3", "duration_seconds": 180}
class VideoFile(MediaFile):
def play(self) -> None:
print(f"Playing video from {self.filepath}...")
def get_metadata(self) -> dict:
return {"codec": "h264", "resolution": "1920x1080"}
ಈಗ, `AudioFile` ಮತ್ತು `VideoFile` ಗಳು `MediaFile` ನಿಂದ ವ್ಯಾಖ್ಯಾನಿಸಲಾದ ಒಪ್ಪಂದವನ್ನು ಪೂರೈಸುವುದರಿಂದ ನಾವು ಅವುಗಳ ಇನ್ಸ್ಟೆನ್ಸ್ಗಳನ್ನು ರಚಿಸಬಹುದು. ಇದು ಎಬಿಸಿಗಳ ಮೂಲಭೂತ ಯಾಂತ್ರಿಕತೆ. ಆದರೆ ನಿಜವಾದ ಶಕ್ತಿ ಬರುವುದು *ಹೇಗೆ* ನಾವು ಈ ಯಾಂತ್ರಿಕತೆಯನ್ನು ಬಳಸುತ್ತೇವೆ ಎಂಬುದರಿಂದ.
ಮೊದಲ ತತ್ವ: ಎಬಿಸಿಗಳು ಫಾರ್ಮಲ್ ಇಂಟರ್ಫೇಸ್ ವಿನ್ಯಾಸವಾಗಿ (ನಾಮಿನಲ್ ಟೈಪಿಂಗ್)
ಎಬಿಸಿಗಳನ್ನು ಬಳಸುವ ಮೊದಲ ಮತ್ತು ಅತ್ಯಂತ ಸಾಂಪ್ರದಾಯಿಕ ವಿಧಾನವೆಂದರೆ ಫಾರ್ಮಲ್ ಇಂಟರ್ಫೇಸ್ ವಿನ್ಯಾಸ. ಈ ವಿಧಾನವು ನಾಮಿನಲ್ ಟೈಪಿಂಗ್ ನಲ್ಲಿ ಬೇರೂರಿದೆ, ಇದು ಜಾವಾ, ಸಿ++, ಅಥವಾ ಸಿ# ನಂತಹ ಭಾಷೆಗಳಿಂದ ಬರುವ ಡೆವಲಪರ್ಗಳಿಗೆ ಪರಿಚಿತವಾದ ಪರಿಕಲ್ಪನೆ. ನಾಮಿನಲ್ ವ್ಯವಸ್ಥೆಯಲ್ಲಿ, ಟೈಪ್ನ ಹೊಂದಾಣಿಕೆಯನ್ನು ಅದರ ಹೆಸರು ಮತ್ತು ಸ್ಪಷ್ಟ ಘೋಷಣೆಯಿಂದ ನಿರ್ಧರಿಸಲಾಗುತ್ತದೆ. ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ, ಒಂದು ಕ್ಲಾಸ್ `MediaFile` ABC ಯಿಂದ ಸ್ಪಷ್ಟವಾಗಿ ಇನ್ಹೆರಿಟ್ ಮಾಡಿದರೆ ಮಾತ್ರ ಅದನ್ನು `MediaFile` ಎಂದು ಪರಿಗಣಿಸಲಾಗುತ್ತದೆ.
ಇದನ್ನು ವೃತ್ತಿಪರ ಪ್ರಮಾಣಪತ್ರದಂತೆ ಯೋಚಿಸಿ. ಪ್ರಮಾಣೀಕೃತ ಪ್ರಾಜೆಕ್ಟ್ ಮ್ಯಾನೇಜರ್ ಆಗಲು, ನೀವು ಕೇವಲ ಹಾಗೆ ವರ್ತಿಸಿದರೆ ಸಾಲದು; ನೀವು ಅಧ್ಯಯನ ಮಾಡಬೇಕು, ನಿರ್ದಿಷ್ಟ ಪರೀಕ್ಷೆಯಲ್ಲಿ ಉತ್ತೀರ್ಣರಾಗಬೇಕು ಮತ್ತು ನಿಮ್ಮ ಅರ್ಹತೆಯನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ಹೇಳುವ ಅಧಿಕೃತ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಪಡೆಯಬೇಕು. ನಿಮ್ಮ ಪ್ರಮಾಣಪತ್ರದ ಹೆಸರು ಮತ್ತು ವಂಶಾವಳಿ ಮುಖ್ಯವಾಗುತ್ತದೆ.
ಈ ಮಾದರಿಯಲ್ಲಿ, ಎಬಿಸಿ ಒಂದು ಬದಲಾಯಿಸಲಾಗದ ಒಪ್ಪಂದವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಅದರಿಂದ ಇನ್ಹೆರಿಟ್ ಮಾಡುವ ಮೂಲಕ, ಒಂದು ಕ್ಲಾಸ್ ವ್ಯವಸ್ಥೆಯ ಉಳಿದ ಭಾಗಕ್ಕೆ ಅಗತ್ಯವಾದ ಕಾರ್ಯವನ್ನು ಒದಗಿಸುವುದಾಗಿ ಔಪಚಾರಿಕ ಭರವಸೆ ನೀಡುತ್ತದೆ.
ಉದಾಹರಣೆ: ಡೇಟಾ ಎಕ್ಸ್ಪೋರ್ಟರ್ ಫ್ರೇಮ್ವರ್ಕ್
ಬಳಕೆದಾರರಿಗೆ ವಿವಿಧ ಫಾರ್ಮ್ಯಾಟ್ಗಳಲ್ಲಿ ಡೇಟಾವನ್ನು ರಫ್ತು ಮಾಡಲು ಅನುಮತಿಸುವ ಫ್ರೇಮ್ವರ್ಕ್ ಅನ್ನು ನಾವು ನಿರ್ಮಿಸುತ್ತಿದ್ದೇವೆ ಎಂದು ಊಹಿಸಿ. ಪ್ರತಿಯೊಂದು ಎಕ್ಸ್ಪೋರ್ಟರ್ ಪ್ಲಗಿನ್ ಕಟ್ಟುನಿಟ್ಟಾದ ರಚನೆಗೆ ಬದ್ಧವಾಗಿರಬೇಕೆಂದು ನಾವು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಬಯಸುತ್ತೇವೆ. ನಾವು `DataExporter` ಇಂಟರ್ಫೇಸ್ ಅನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಬಹುದು.
import abc
from datetime import datetime
class DataExporter(abc.ABC):
"""ಡೇಟಾ ರಫ್ತು ಮಾಡುವ ಕ್ಲಾಸ್ಗಳಿಗೆ ಒಂದು ಔಪಚಾರಿಕ ಇಂಟರ್ಫೇಸ್."""
@abc.abstractmethod
def export(self, data: list[dict]) -> str:
"""ಡೇಟಾವನ್ನು ರಫ್ತು ಮಾಡುತ್ತದೆ ಮತ್ತು ಸ್ಟೇಟಸ್ ಸಂದೇಶವನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ."""
pass
def get_timestamp(self) -> str:
"""ಎಲ್ಲಾ ಸಬ್ಕ್ಲಾಸ್ಗಳಿಂದ ಹಂಚಿಕೊಳ್ಳಲಾದ ಕಾಂಕ್ರೀಟ್ ಸಹಾಯಕ ಮೆಥಡ್."""
return datetime.utcnow().isoformat()
class CSVExporter(DataExporter):
def export(self, data: list[dict]) -> str:
filename = f"export_{self.get_timestamp()}.csv"
print(f"Exporting {len(data)} rows to {filename}")
# ... actual CSV writing logic ...
return f"Successfully exported to {filename}"
class JSONExporter(DataExporter):
def export(self, data: list[dict]) -> str:
filename = f"export_{self.get_timestamp()}.json"
print(f"Exporting {len(data)} records to {filename}")
# ... actual JSON writing logic ...
return f"Successfully exported to {filename}"
ಇಲ್ಲಿ, `CSVExporter` ಮತ್ತು `JSONExporter` ಗಳು ಸ್ಪಷ್ಟವಾಗಿ ಮತ್ತು ಪರಿಶೀಲಿಸಬಹುದಾದ `DataExporter` ಗಳಾಗಿವೆ. ನಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ನ ಕೋರ್ ಲಾಜಿಕ್ ಈ ಒಪ್ಪಂದವನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಅವಲಂಬಿಸಬಹುದು:
def run_export_process(exporter: DataExporter, data_to_export: list[dict]):
print("--- Starting export process ---")
if not isinstance(exporter, DataExporter):
raise TypeError("Exporter must be a valid DataExporter implementation.")
status = exporter.export(data_to_export)
print(f"Process finished with status: {status}")
# ಬಳಕೆ
data = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
run_export_process(CSVExporter(), data)
run_export_process(JSONExporter(), data)
ಎಬಿಸಿಯು `get_timestamp()` ಎಂಬ ಕಾಂಕ್ರೀಟ್ ಮೆಥಡ್ ಅನ್ನು ಸಹ ಒದಗಿಸುತ್ತದೆ, ಇದು ಅದರ ಎಲ್ಲಾ ಮಕ್ಕಳಿಗೆ ಹಂಚಿಕೆಯ ಕಾರ್ಯವನ್ನು ನೀಡುತ್ತದೆ ಎಂಬುದನ್ನು ಗಮನಿಸಿ. ಇದು ಇಂಟರ್ಫೇಸ್-ಆಧಾರಿತ ವಿನ್ಯಾಸದಲ್ಲಿ ಒಂದು ಸಾಮಾನ್ಯ ಮತ್ತು ಶಕ್ತಿಶಾಲಿ ಮಾದರಿಯಾಗಿದೆ.
ಫಾರ್ಮಲ್ ಇಂಟರ್ಫೇಸ್ ವಿಧಾನದ ಅನುಕೂಲಗಳು ಮತ್ತು ಅನಾನುಕೂಲಗಳು
ಅನುಕೂಲಗಳು:
- ಅಸ್ಪಷ್ಟವಲ್ಲದ ಮತ್ತು ಸ್ಪಷ್ಟ: ಒಪ್ಪಂದವು ಸಂಪೂರ್ಣವಾಗಿ ಸ್ಪಷ್ಟವಾಗಿದೆ. ಒಬ್ಬ ಡೆವಲಪರ್ `class CSVExporter(DataExporter):` ಎಂಬ ಇನ್ಹೆರಿಟೆನ್ಸ್ ಲೈನ್ ಅನ್ನು ನೋಡಿ ತಕ್ಷಣವೇ ಕ್ಲಾಸ್ನ ಪಾತ್ರ ಮತ್ತು ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಬಹುದು.
- ಟೂಲಿಂಗ್-ಸ್ನೇಹಿ: ಐಡಿಇಗಳು (IDEs), ಲಿಂಟರ್ಗಳು ಮತ್ತು ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ ಪರಿಕರಗಳು ಸುಲಭವಾಗಿ ಒಪ್ಪಂದವನ್ನು ಪರಿಶೀಲಿಸಬಹುದು, ಅತ್ಯುತ್ತಮ ಆಟೋಕಂಪ್ಲೀಷನ್ ಮತ್ತು ದೋಷ ಪರಿಶೀಲನೆಯನ್ನು ಒದಗಿಸುತ್ತವೆ.
- ಹಂಚಿಕೆಯ ಕಾರ್ಯ: ಎಬಿಸಿಗಳು ಕಾಂಕ್ರೀಟ್ ಮೆಥಡ್ಗಳನ್ನು ಒದಗಿಸಬಹುದು, ನಿಜವಾದ ಬೇಸ್ ಕ್ಲಾಸ್ ಆಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತವೆ ಮತ್ತು ಕೋಡ್ ನಕಲು ಮಾಡುವುದನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತವೆ.
- ಪರಿಚಿತತೆ: ಈ ಮಾದರಿಯು ಇತರ ಬಹುಪಾಲು ಆಬ್ಜೆಕ್ಟ್-ಓರಿಯೆಂಟೆಡ್ ಭಾಷೆಗಳ ಡೆವಲಪರ್ಗಳಿಗೆ ತಕ್ಷಣವೇ ಗುರುತಿಸಲ್ಪಡುತ್ತದೆ.
ಅನಾನುಕೂಲಗಳು:
- ಬಿಗಿಯಾದ ಜೋಡಣೆ: ಕಾಂಕ್ರೀಟ್ ಕ್ಲಾಸ್ ಈಗ ನೇರವಾಗಿ ಎಬಿಸಿಗೆ ಬಂಧಿಸಲ್ಪಟ್ಟಿದೆ. ಎಬಿಸಿಯನ್ನು ಸ್ಥಳಾಂತರಿಸಬೇಕಾದರೆ ಅಥವಾ ಬದಲಾಯಿಸಬೇಕಾದರೆ, ಎಲ್ಲಾ ಸಬ್ಕ್ಲಾಸ್ಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ.
- ಕಠಿಣತೆ: ಇದು ಕಟ್ಟುನಿಟ್ಟಾದ ಶ್ರೇಣಿ ವ್ಯವಸ್ಥೆಯನ್ನು ಒತ್ತಾಯಿಸುತ್ತದೆ. ಒಂದು ಕ್ಲಾಸ್ ತಾರ್ಕಿಕವಾಗಿ ಎಕ್ಸ್ಪೋರ್ಟರ್ ಆಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಬಹುದಾದರೂ, ಅದು ಈಗಾಗಲೇ ಬೇರೆ, ಅತ್ಯಗತ್ಯ ಬೇಸ್ ಕ್ಲಾಸ್ ನಿಂದ ಇನ್ಹೆರಿಟ್ ಆಗಿದ್ದರೆ ಏನು ಮಾಡುವುದು? ಪೈಥಾನ್ನ ಮಲ್ಟಿಪಲ್ ಇನ್ಹೆರಿಟೆನ್ಸ್ ಇದನ್ನು ಪರಿಹರಿಸಬಲ್ಲದು, ಆದರೆ ಅದು ತನ್ನದೇ ಆದ ಸಂಕೀರ್ಣತೆಗಳನ್ನು (ಡೈಮಂಡ್ ಪ್ರಾಬ್ಲಮ್ ನಂತಹ) ಪರಿಚಯಿಸಬಹುದು.
- ಆಕ್ರಮಣಕಾರಿ: ಇದನ್ನು ಥರ್ಡ್-ಪಾರ್ಟಿ ಕೋಡ್ ಅನ್ನು ಅಳವಡಿಸಿಕೊಳ್ಳಲು ಬಳಸಲಾಗುವುದಿಲ್ಲ. ನೀವು `export()` ಮೆಥಡ್ ಹೊಂದಿರುವ ಕ್ಲಾಸ್ ಅನ್ನು ಒದಗಿಸುವ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸುತ್ತಿದ್ದರೆ, ಅದನ್ನು ಸಬ್ಕ್ಲಾಸ್ ಮಾಡದೆ `DataExporter` ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ (ಇದು ಸಾಧ್ಯವಾಗದಿರಬಹುದು ಅಥವಾ ಅಪೇಕ್ಷಣೀಯವಾಗಿರದಿರಬಹುದು).
ಎರಡನೇ ತತ್ವ: ಎಬಿಸಿಗಳು ಪ್ರೋಟೋಕಾಲ್ ಇಂಪ್ಲಿಮೆಂಟೇಶನ್ ಆಗಿ (ಸ್ಟ್ರಕ್ಚರಲ್ ಟೈಪಿಂಗ್)
ಎರಡನೇ, ಹೆಚ್ಚು "ಪೈಥಾನಿಕ್" ತತ್ವವು ಡಕ್ ಟೈಪಿಂಗ್ಗೆ ಅನುಗುಣವಾಗಿರುತ್ತದೆ. ಈ ವಿಧಾನವು ಸ್ಟ್ರಕ್ಚರಲ್ ಟೈಪಿಂಗ್ ಅನ್ನು ಬಳಸುತ್ತದೆ, ಇಲ್ಲಿ ಹೊಂದಾಣಿಕೆಯನ್ನು ಹೆಸರು ಅಥವಾ ವಂಶಾವಳಿಯಿಂದಲ್ಲ, ಬದಲಿಗೆ ರಚನೆ ಮತ್ತು ನಡವಳಿಕೆಯಿಂದ ನಿರ್ಧರಿಸಲಾಗುತ್ತದೆ. ಒಂದು ಆಬ್ಜೆಕ್ಟ್ ಕೆಲಸ ಮಾಡಲು ಬೇಕಾದ ಮೆಥಡ್ಗಳು ಮತ್ತು ಅಟ್ರಿಬ್ಯೂಟ್ಗಳನ್ನು ಹೊಂದಿದ್ದರೆ, ಅದರ ಘೋಷಿತ ಕ್ಲಾಸ್ ಶ್ರೇಣಿಯನ್ನು ಲೆಕ್ಕಿಸದೆ, ಅದನ್ನು ಆ ಕೆಲಸಕ್ಕೆ ಸರಿಯಾದ ಟೈಪ್ ಎಂದು ಪರಿಗಣಿಸಲಾಗುತ್ತದೆ.
ಈಜುವ ಸಾಮರ್ಥ್ಯದ ಬಗ್ಗೆ ಯೋಚಿಸಿ. ಈಜುಗಾರ ಎಂದು ಪರಿಗಣಿಸಲು, ನಿಮಗೆ ಪ್ರಮಾಣಪತ್ರ ಅಥವಾ "ಈಜುಗಾರ" ಕುಟುಂಬದ ವಂಶವೃಕ್ಷದ ಭಾಗವಾಗಿರಬೇಕಾಗಿಲ್ಲ. ನೀವು ಮುಳುಗದೆ ನೀರಿನಲ್ಲಿ ಚಲಿಸಬಲ್ಲವರಾಗಿದ್ದರೆ, ನೀವು ರಚನಾತ್ಮಕವಾಗಿ ಈಜುಗಾರ. ಒಬ್ಬ ವ್ಯಕ್ತಿ, ಒಂದು ನಾಯಿ, ಮತ್ತು ಒಂದು ಬಾತುಕೋಳಿ ಎಲ್ಲರೂ ಈಜುಗಾರರಾಗಬಹುದು.
ಎಬಿಸಿಗಳನ್ನು ಈ ಪರಿಕಲ್ಪನೆಯನ್ನು ಔಪಚಾರಿಕಗೊಳಿಸಲು ಬಳಸಬಹುದು. ಇನ್ಹೆರಿಟೆನ್ಸ್ಗೆ ಒತ್ತಾಯಿಸುವ ಬದಲು, ನಾವು ಅಗತ್ಯ ಪ್ರೋಟೋಕಾಲ್ ಅನ್ನು ಇಂಪ್ಲಿಮೆಂಟ್ ಮಾಡಿದರೆ ಇತರ ಕ್ಲಾಸ್ಗಳನ್ನು ಅದರ ವರ್ಚುವಲ್ ಸಬ್ಕ್ಲಾಸ್ಗಳಾಗಿ ಗುರುತಿಸುವ ಎಬಿಸಿಯನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಬಹುದು. ಇದನ್ನು `__subclasshook__` ಎಂಬ ವಿಶೇಷ ಮ್ಯಾಜಿಕ್ ಮೆಥಡ್ ಮೂಲಕ ಸಾಧಿಸಲಾಗುತ್ತದೆ.
ನೀವು `isinstance(obj, MyABC)` ಅಥವಾ `issubclass(SomeClass, MyABC)` ಎಂದು ಕರೆದಾಗ, ಪೈಥಾನ್ ಮೊದಲು ಸ್ಪಷ್ಟ ಇನ್ಹೆರಿಟೆನ್ಸ್ಗಾಗಿ ಪರಿಶೀಲಿಸುತ್ತದೆ. ಅದು ವಿಫಲವಾದರೆ, `MyABC` ಗೆ `__subclasshook__` ಮೆಥಡ್ ಇದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸುತ್ತದೆ. ಹಾಗಿದ್ದರೆ, ಪೈಥಾನ್ ಅದನ್ನು ಕರೆದು, "ಹೇ, ನೀವು ಈ ಕ್ಲಾಸ್ ಅನ್ನು ನಿಮ್ಮ ಸಬ್ಕ್ಲಾಸ್ ಎಂದು ಪರಿಗಣಿಸುತ್ತೀರಾ?" ಎಂದು ಕೇಳುತ್ತದೆ. ಇದು ಎಬಿಸಿಗೆ ಅದರ ಸದಸ್ಯತ್ವದ ಮಾನದಂಡಗಳನ್ನು ರಚನೆಯ ಆಧಾರದ ಮೇಲೆ ವ್ಯಾಖ್ಯಾನಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ.
ಉದಾಹರಣೆ: ಒಂದು `Serializable` ಪ್ರೋಟೋಕಾಲ್
ಡಿಕ್ಷನರಿಗೆ ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದಾದ ಆಬ್ಜೆಕ್ಟ್ಗಳಿಗಾಗಿ ಒಂದು ಪ್ರೋಟೋಕಾಲ್ ಅನ್ನು ವ್ಯಾಖ್ಯಾನಿಸೋಣ. ನಮ್ಮ ಸಿಸ್ಟಂನಲ್ಲಿರುವ ಪ್ರತಿಯೊಂದು ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದಾದ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಸಾಮಾನ್ಯ ಬೇಸ್ ಕ್ಲಾಸ್ನಿಂದ ಇನ್ಹೆರಿಟ್ ಮಾಡಲು ನಾವು ಒತ್ತಾಯಿಸಲು ಬಯಸುವುದಿಲ್ಲ. ಅವು ಡೇಟಾಬೇಸ್ ಮಾಡೆಲ್ಗಳು, ಡೇಟಾ ಟ್ರಾನ್ಸ್ಫರ್ ಆಬ್ಜೆಕ್ಟ್ಗಳು, ಅಥವಾ ಸರಳ ಕಂಟೇನರ್ಗಳಾಗಿರಬಹುದು.
import abc
class Serializable(abc.ABC):
@abc.abstractmethod
def to_dict(self) -> dict:
pass
@classmethod
def __subclasshook__(cls, C):
if cls is Serializable:
# 'to_dict' C ಯ ಮೆಥಡ್ ರೆಸಲ್ಯೂಶನ್ ಆರ್ಡರ್ನಲ್ಲಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ
if any("to_dict" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
ಈಗ, ಕೆಲವು ಕ್ಲಾಸ್ಗಳನ್ನು ರಚಿಸೋಣ. ನಿರ್ಣಾಯಕವಾಗಿ, ಇವುಗಳಲ್ಲಿ ಯಾವುದೂ `Serializable` ನಿಂದ ಇನ್ಹೆರಿಟ್ ಆಗುವುದಿಲ್ಲ.
class User:
def __init__(self, name: str, email: str):
self.name = name
self.email = email
def to_dict(self) -> dict:
return {"name": self.name, "email": self.email}
class Product:
def __init__(self, sku: str, price: float):
self.sku = sku
self.price = price
# ಈ ಕ್ಲಾಸ್ ಪ್ರೋಟೋಕಾಲ್ಗೆ ಅನುಗುಣವಾಗಿಲ್ಲ
class Configuration:
def __init__(self, setting: str):
self.setting = setting
ಅವುಗಳನ್ನು ನಮ್ಮ ಪ್ರೋಟೋಕಾಲ್ನೊಂದಿಗೆ ಪರಿಶೀಲಿಸೋಣ:
print(f"User ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? {isinstance(User('Test', 't@t.com'), Serializable)}")
print(f"Product ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? {isinstance(Product('T-1000', 99.99), Serializable)}")
print(f"Configuration ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? {isinstance(Configuration('ON'), Serializable)}")
# ಔಟ್ಪುಟ್:
# User ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? True
# Product ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? False <- ನಿಲ್ಲಿ, ಏಕೆ? ಇದನ್ನು ಸರಿಪಡಿಸೋಣ.
# Configuration ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? False
ಆಹಾ, ಒಂದು ಆಸಕ್ತಿದಾಯಕ ದೋಷ! ನಮ್ಮ `Product` ಕ್ಲಾಸ್ನಲ್ಲಿ `to_dict` ಮೆಥಡ್ ಇಲ್ಲ. ಅದನ್ನು ಸೇರಿಸೋಣ.
class Product:
def __init__(self, sku: str, price: float):
self.sku = sku
self.price = price
def to_dict(self) -> dict: # ಮೆಥಡ್ ಸೇರಿಸಲಾಗುತ್ತಿದೆ
return {"sku": self.sku, "price": self.price}
print(f"Product ಈಗ ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? {isinstance(Product('T-1000', 99.99), Serializable)}")
# ಔಟ್ಪುಟ್:
# Product ಈಗ ಸೀರಿಯಲೈಜ್ ಮಾಡಬಹುದೇ? True
`User` ಮತ್ತು `Product` ಯಾವುದೇ ಸಾಮಾನ್ಯ ಪೇರೆಂಟ್ ಕ್ಲಾಸ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳದಿದ್ದರೂ (`object` ಹೊರತುಪಡಿಸಿ), ನಮ್ಮ ಸಿಸ್ಟಂ ಅವೆರಡನ್ನೂ `Serializable` ಎಂದು ಪರಿಗಣಿಸಬಹುದು ಏಕೆಂದರೆ ಅವು ಪ್ರೋಟೋಕಾಲ್ ಅನ್ನು ಪೂರೈಸುತ್ತವೆ. ಇದು ಡಿಕಪ್ಲಿಂಗ್ (decoupling) ಗಾಗಿ ಅತ್ಯಂತ ಶಕ್ತಿಶಾಲಿಯಾಗಿದೆ.
ಪ್ರೋಟೋಕಾಲ್ ವಿಧಾನದ ಅನುಕೂಲಗಳು ಮತ್ತು ಅನಾನುಕೂಲಗಳು
ಅನುಕೂಲಗಳು:
- ಗರಿಷ್ಠ ನಮ್ಯತೆ: ಅತ್ಯಂತ ಸಡಿಲವಾದ ಜೋಡಣೆಯನ್ನು ಉತ್ತೇಜಿಸುತ್ತದೆ. ಘಟಕಗಳು ನಡವಳಿಕೆಯ ಬಗ್ಗೆ ಮಾತ್ರ ಕಾಳಜಿ ವಹಿಸುತ್ತವೆ, ಇಂಪ್ಲಿಮೆಂಟೇಶನ್ ವಂಶಾವಳಿಯ ಬಗ್ಗೆ ಅಲ್ಲ.
- ಹೊಂದಿಕೊಳ್ಳುವಿಕೆ: ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕೋಡ್ ಅನ್ನು, ವಿಶೇಷವಾಗಿ ಥರ್ಡ್-ಪಾರ್ಟಿ ಲೈಬ್ರರಿಗಳಿಂದ, ಮೂಲ ಕೋಡ್ ಅನ್ನು ಬದಲಾಯಿಸದೆ ನಿಮ್ಮ ಸಿಸ್ಟಂನ ಇಂಟರ್ಫೇಸ್ಗಳಿಗೆ ಹೊಂದಿಕೊಳ್ಳುವಂತೆ ಮಾಡಲು ಇದು ಪರಿಪೂರ್ಣವಾಗಿದೆ.
- ಸಂಯೋಜನೆಯನ್ನು ಉತ್ತೇಜಿಸುತ್ತದೆ: ಆಳವಾದ, ಕಠಿಣವಾದ ಇನ್ಹೆರಿಟೆನ್ಸ್ ಟ್ರೀಗಳ ಮೂಲಕ ಆಬ್ಜೆಕ್ಟ್ಗಳನ್ನು ನಿರ್ಮಿಸುವ ಬದಲು, ಸ್ವತಂತ್ರ ಸಾಮರ್ಥ್ಯಗಳಿಂದ ನಿರ್ಮಿಸುವ ವಿನ್ಯಾಸ ಶೈಲಿಯನ್ನು ಪ್ರೋತ್ಸಾಹಿಸುತ್ತದೆ.
ಅನಾನುಕೂಲಗಳು:
- ಸೂಚ್ಯ ಒಪ್ಪಂದ: ಒಂದು ಕ್ಲಾಸ್ ಮತ್ತು ಅದು ಇಂಪ್ಲಿಮೆಂಟ್ ಮಾಡುವ ಪ್ರೋಟೋಕಾಲ್ ನಡುವಿನ ಸಂಬಂಧವು ಕ್ಲಾಸ್ ಡೆಫಿನಿಷನ್ನಿಂದ ತಕ್ಷಣ ಸ್ಪಷ್ಟವಾಗುವುದಿಲ್ಲ. `User` ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು `Serializable` ಎಂದು ಏಕೆ ಪರಿಗಣಿಸಲಾಗುತ್ತಿದೆ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಡೆವಲಪರ್ ಕೋಡ್ಬೇಸ್ನಲ್ಲಿ ಹುಡುಕಬೇಕಾಗಬಹುದು.
- ರನ್ಟೈಮ್ ಓವರ್ಹೆಡ್: `isinstance` ಚೆಕ್ ನಿಧಾನವಾಗಿರಬಹುದು, ಏಕೆಂದರೆ ಅದು `__subclasshook__` ಅನ್ನು ಇನ್ವೋಕ್ ಮಾಡಬೇಕು ಮತ್ತು ಕ್ಲಾಸ್ನ ಮೆಥಡ್ಗಳ ಮೇಲೆ ಪರಿಶೀಲನೆಗಳನ್ನು ನಡೆಸಬೇಕು.
- ಸಂಕೀರ್ಣತೆಯ ಸಾಧ್ಯತೆ: ಪ್ರೋಟೋಕಾಲ್ ಅನೇಕ ಮೆಥಡ್ಗಳು, ಆರ್ಗ್ಯುಮೆಂಟ್ಗಳು, ಅಥವಾ ರಿಟರ್ನ್ ಟೈಪ್ಗಳನ್ನು ಒಳಗೊಂಡಿದ್ದರೆ `__subclasshook__` ಒಳಗಿನ ಲಾಜಿಕ್ ಸಾಕಷ್ಟು ಸಂಕೀರ್ಣವಾಗಬಹುದು.
ಆಧುನಿಕ ಸಂಶ್ಲೇಷಣೆ: `typing.Protocol` ಮತ್ತು ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್
ದೊಡ್ಡ-ಪ್ರಮಾಣದ ಸಿಸ್ಟಮ್ಗಳಲ್ಲಿ ಪೈಥಾನ್ನ ಬಳಕೆ ಹೆಚ್ಚಾದಂತೆ, ಉತ್ತಮ ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ಗಾಗಿ ಬಯಕೆಯೂ ಹೆಚ್ಚಾಯಿತು. `__subclasshook__` ವಿಧಾನವು ಶಕ್ತಿಯುತವಾಗಿದೆ ಆದರೆ ಇದು ಸಂಪೂರ್ಣವಾಗಿ ರನ್ಟೈಮ್ ಯಾಂತ್ರಿಕತೆಯಾಗಿದೆ. ನಾವು ಕೋಡ್ ಅನ್ನು ರನ್ ಮಾಡುವ *ಮೊದಲೇ* ಸ್ಟ್ರಕ್ಚರಲ್ ಟೈಪಿಂಗ್ನ ಪ್ರಯೋಜನಗಳನ್ನು ಪಡೆದರೆ ಹೇಗೆ?
ಇದು PEP 544 ರಲ್ಲಿ `typing.Protocol` ಪರಿಚಯಕ್ಕೆ ಕಾರಣವಾಯಿತು. ಇದು ಮುಖ್ಯವಾಗಿ Mypy, Pyright, ಅಥವಾ PyCharm ನ ಇನ್ಸ್ಪೆಕ್ಟರ್ನಂತಹ ಸ್ಟ್ಯಾಟಿಕ್ ಟೈಪ್ ಚೆಕರ್ಗಳಿಗಾಗಿ ಉದ್ದೇಶಿಸಲಾದ ಪ್ರೋಟೋಕಾಲ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಲು ಒಂದು ಪ್ರಮಾಣೀಕೃತ ಮತ್ತು ಸೊಗಸಾದ ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತದೆ.
ಒಂದು `Protocol` ಕ್ಲಾಸ್ ನಮ್ಮ `__subclasshook__` ಉದಾಹರಣೆಯಂತೆಯೇ ಕೆಲಸ ಮಾಡುತ್ತದೆ ಆದರೆ ಬಾಯ್ಲರ್ಪ್ಲೇಟ್ ಇಲ್ಲದೆ. ನೀವು ಕೇವಲ ಮೆಥಡ್ಗಳು ಮತ್ತು ಅವುಗಳ ಸಿಗ್ನೇಚರ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸುತ್ತೀರಿ. ಹೊಂದಾಣಿಕೆಯಾಗುವ ಮೆಥಡ್ಗಳು ಮತ್ತು ಸಿಗ್ನೇಚರ್ಗಳನ್ನು ಹೊಂದಿರುವ ಯಾವುದೇ ಕ್ಲಾಸ್ ಅನ್ನು ಸ್ಟ್ಯಾಟಿಕ್ ಟೈಪ್ ಚೆಕರ್ ರಚನಾತ್ಮಕವಾಗಿ ಹೊಂದಿಕೊಳ್ಳುತ್ತದೆ ಎಂದು ಪರಿಗಣಿಸುತ್ತದೆ.
ಉದಾಹರಣೆ: ಒಂದು `Quacker` ಪ್ರೋಟೋಕಾಲ್
ಕ್ಲಾಸಿಕ್ ಡಕ್ ಟೈಪಿಂಗ್ ಉದಾಹರಣೆಯನ್ನು ಆಧುನಿಕ ಪರಿಕರಗಳೊಂದಿಗೆ ಮತ್ತೊಮ್ಮೆ ನೋಡೋಣ.
from typing import Protocol
class Quacker(Protocol):
def quack(self, volume: int) -> str:
"""ಕ್ವಾಕ್ ಶಬ್ದವನ್ನು ಉತ್ಪಾದಿಸುತ್ತದೆ."""
... # ಗಮನಿಸಿ: ಪ್ರೋಟೋಕಾಲ್ ಮೆಥಡ್ನ ಬಾಡಿ ಅಗತ್ಯವಿಲ್ಲ
class Duck:
def quack(self, volume: int) -> str:
return f"QUACK! (at volume {volume})"
class Dog:
def bark(self, volume: int) -> str:
return f"WOOF! (at volume {volume})"
def make_sound(animal: Quacker):
print(animal.quack(10))
make_sound(Duck()) # ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ ಪಾಸ್ ಆಗುತ್ತದೆ
make_sound(Dog()) # ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ ವಿಫಲವಾಗುತ್ತದೆ!
ನೀವು ಈ ಕೋಡ್ ಅನ್ನು Mypy ನಂತಹ ಟೈಪ್ ಚೆಕರ್ ಮೂಲಕ ರನ್ ಮಾಡಿದರೆ, ಅದು `make_sound(Dog())` ಲೈನ್ ಅನ್ನು ದೋಷದೊಂದಿಗೆ ಫ್ಲ್ಯಾಗ್ ಮಾಡುತ್ತದೆ: `Argument 1 to "make_sound" has incompatible type "Dog"; expected "Quacker"`. `Dog` ಕ್ಲಾಸ್ `quack` ಮೆಥಡ್ ಹೊಂದಿಲ್ಲದ ಕಾರಣ ಅದು `Quacker` ಪ್ರೋಟೋಕಾಲ್ ಅನ್ನು ಪೂರೈಸುವುದಿಲ್ಲ ಎಂದು ಟೈಪ್ ಚೆಕರ್ ಅರ್ಥಮಾಡಿಕೊಳ್ಳುತ್ತದೆ. ಇದು ಕೋಡ್ ಕಾರ್ಯಗತಗೊಳ್ಳುವ ಮೊದಲೇ ದೋಷವನ್ನು ಹಿಡಿಯುತ್ತದೆ.
`@runtime_checkable` ಜೊತೆಗೆ ರನ್ಟೈಮ್ ಪ್ರೋಟೋಕಾಲ್ಗಳು
ಪೂರ್ವನಿಯೋಜಿತವಾಗಿ, `typing.Protocol` ಕೇವಲ ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ಗಾಗಿ ಮಾತ್ರ. ನೀವು ಅದನ್ನು ರನ್ಟೈಮ್ `isinstance` ಚೆಕ್ನಲ್ಲಿ ಬಳಸಲು ಪ್ರಯತ್ನಿಸಿದರೆ, ನಿಮಗೆ ದೋಷ ಬರುತ್ತದೆ.
# isinstance(Duck(), Quacker) # -> TypeError: ಪ್ರೋಟೋಕಾಲ್ 'Quacker' ಅನ್ನು ಇನ್ಸ್ಟೆನ್ಶಿಯೇಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ
ಆದಾಗ್ಯೂ, `@runtime_checkable` ಡೆಕೋರೇಟರ್ನೊಂದಿಗೆ ನೀವು ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ ಮತ್ತು ರನ್ಟೈಮ್ ನಡವಳಿಕೆಯ ನಡುವಿನ ಅಂತರವನ್ನು ಕಡಿಮೆ ಮಾಡಬಹುದು. ಇದು ಮೂಲಭೂತವಾಗಿ `__subclasshook__` ಲಾಜಿಕ್ ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿಮಗಾಗಿ ರಚಿಸಲು ಪೈಥಾನ್ಗೆ ಹೇಳುತ್ತದೆ.
from typing import Protocol, runtime_checkable
@runtime_checkable
class Quacker(Protocol):
def quack(self, volume: int) -> str: ...
class Duck:
def quack(self, volume: int) -> str: return "..."
print(f"Duck ಒಂದು Quacker ನ ಇನ್ಸ್ಟೆನ್ಸ್ ಆಗಿದೆಯೇ? {isinstance(Duck(), Quacker)}")
# ಔಟ್ಪುಟ್:
# Duck ಒಂದು Quacker ನ ಇನ್ಸ್ಟೆನ್ಸ್ ಆಗಿದೆಯೇ? True
ಇದು ನಿಮಗೆ ಎರಡೂ ಪ್ರಪಂಚಗಳ ಅತ್ಯುತ್ತಮವಾದದ್ದನ್ನು ನೀಡುತ್ತದೆ: ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ಗಾಗಿ ಸ್ವಚ್ಛ, ಡಿಕ್ಲರೇಟಿವ್ ಪ್ರೋಟೋಕಾಲ್ ವ್ಯಾಖ್ಯಾನಗಳು, ಮತ್ತು ಅಗತ್ಯವಿದ್ದಾಗ ರನ್ಟೈಮ್ ಮೌಲ್ಯೀಕರಣದ ಆಯ್ಕೆ. ಆದಾಗ್ಯೂ, ಪ್ರೋಟೋಕಾಲ್ಗಳ ಮೇಲಿನ ರನ್ಟೈಮ್ ಚೆಕ್ಗಳು ಸ್ಟ್ಯಾಂಡರ್ಡ್ `isinstance` ಕರೆಗಳಿಗಿಂತ ನಿಧಾನವಾಗಿರುತ್ತವೆ, ಆದ್ದರಿಂದ ಅವುಗಳನ್ನು ವಿವೇಚನೆಯಿಂದ ಬಳಸಬೇಕು ಎಂಬುದನ್ನು ನೆನಪಿನಲ್ಲಿಡಿ.
ಪ್ರಾಯೋಗಿಕ ನಿರ್ಧಾರ-ತೆಗೆದುಕೊಳ್ಳುವಿಕೆ: ಜಾಗತಿಕ ಡೆವಲಪರ್ಗಾಗಿ ಒಂದು ಮಾರ್ಗದರ್ಶಿ
ಹಾಗಾದರೆ, ನೀವು ಯಾವ ವಿಧಾನವನ್ನು ಆರಿಸಬೇಕು? ಉತ್ತರವು ಸಂಪೂರ್ಣವಾಗಿ ನಿಮ್ಮ ನಿರ್ದಿಷ್ಟ ಬಳಕೆಯ ಪ್ರಕರಣವನ್ನು ಅವಲಂಬಿಸಿರುತ್ತದೆ. ಅಂತರರಾಷ್ಟ್ರೀಯ ಸಾಫ್ಟ್ವೇರ್ ಯೋಜನೆಗಳಲ್ಲಿನ ಸಾಮಾನ್ಯ ಸನ್ನಿವೇಶಗಳನ್ನು ಆಧರಿಸಿ ಇಲ್ಲಿ ಪ್ರಾಯೋಗಿಕ ಮಾರ್ಗದರ್ಶಿ ಇದೆ.
ಸನ್ನಿವೇಶ 1: ಜಾಗತಿಕ SaaS ಉತ್ಪನ್ನಕ್ಕಾಗಿ ಪ್ಲಗಿನ್ ಆರ್ಕಿಟೆಕ್ಚರ್ ನಿರ್ಮಿಸುವುದು
ನೀವು ಒಂದು ಸಿಸ್ಟಮ್ (ಉದಾಹರಣೆಗೆ, ಇ-ಕಾಮರ್ಸ್ ಪ್ಲಾಟ್ಫಾರ್ಮ್, ಸಿಎಮ್ಎಸ್) ಅನ್ನು ವಿನ್ಯಾಸಗೊಳಿಸುತ್ತಿದ್ದೀರಿ, ಅದನ್ನು ಪ್ರಪಂಚದಾದ್ಯಂತದ ಫಸ್ಟ್-ಪಾರ್ಟಿ ಮತ್ತು ಥರ್ಡ್-ಪಾರ್ಟಿ ಡೆವಲಪರ್ಗಳು ವಿಸ್ತರಿಸುತ್ತಾರೆ. ಈ ಪ್ಲಗಿನ್ಗಳು ನಿಮ್ಮ ಕೋರ್ ಅಪ್ಲಿಕೇಶನ್ನೊಂದಿಗೆ ಆಳವಾಗಿ ಸಂಯೋಜನೆಗೊಳ್ಳಬೇಕಾಗುತ್ತದೆ.
- ಶಿಫಾರಸು: ಫಾರ್ಮಲ್ ಇಂಟರ್ಫೇಸ್ (ನಾಮಿನಲ್ `abc.ABC`).
- ಕಾರಣ: ಸ್ಪಷ್ಟತೆ, ಸ್ಥಿರತೆ, ಮತ್ತು ನಿಖರತೆ ಅತ್ಯಂತ ಮುಖ್ಯ. ನಿಮಗೆ ಬದಲಾಯಿಸಲಾಗದ ಒಪ್ಪಂದ ಬೇಕು, ಪ್ಲಗಿನ್ ಡೆವಲಪರ್ಗಳು ನಿಮ್ಮ `BasePlugin` ABC ಯಿಂದ ಇನ್ಹೆರಿಟ್ ಮಾಡುವ ಮೂಲಕ ಪ್ರಜ್ಞಾಪೂರ್ವಕವಾಗಿ ಒಪ್ಪಿಕೊಳ್ಳಬೇಕು. ಇದು ನಿಮ್ಮ API ಅನ್ನು ಅಸ್ಪಷ್ಟವಲ್ಲದಂತೆ ಮಾಡುತ್ತದೆ. ನೀವು ಬೇಸ್ ಕ್ಲಾಸ್ನಲ್ಲಿ ಅಗತ್ಯ ಸಹಾಯಕ ಮೆಥಡ್ಗಳನ್ನು (ಉದಾಹರಣೆಗೆ, ಲಾಗಿಂಗ್, ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಪ್ರವೇಶಿಸುವುದು, ಅಂತರರಾಷ್ಟ್ರೀಕರಣಕ್ಕಾಗಿ) ಸಹ ಒದಗಿಸಬಹುದು, ಇದು ನಿಮ್ಮ ಡೆವಲಪರ್ ಪರಿಸರ ವ್ಯವಸ್ಥೆಗೆ ಒಂದು ದೊಡ್ಡ ಪ್ರಯೋಜನವಾಗಿದೆ.
ಸನ್ನಿವೇಶ 2: ಬಹು, ಸಂಬಂಧವಿಲ್ಲದ API ಗಳಿಂದ ಹಣಕಾಸು ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುವುದು
ನಿಮ್ಮ ಫಿನ್ಟೆಕ್ ಅಪ್ಲಿಕೇಶನ್ ವಿವಿಧ ಜಾಗತಿಕ ಪಾವತಿ ಗೇಟ್ವೇಗಳಿಂದ ವಹಿವಾಟು ಡೇಟಾವನ್ನು ಬಳಸಬೇಕಾಗಿದೆ: ಸ್ಟ್ರೈಪ್, ಪೇಪಾಲ್, ಅಡ್ಯೆನ್, ಮತ್ತು ಬಹುಶಃ ಲ್ಯಾಟಿನ್ ಅಮೇರಿಕಾದಲ್ಲಿನ ಮರ್ಕಾಡೊ ಪಾಗೊದಂತಹ ಪ್ರಾದೇಶಿಕ ಪೂರೈಕೆದಾರರು. ಅವರ SDK ಗಳು ಹಿಂತಿರುಗಿಸುವ ಆಬ್ಜೆಕ್ಟ್ಗಳು ನಿಮ್ಮ ನಿಯಂತ್ರಣದಲ್ಲಿರುವುದಿಲ್ಲ.
- ಶಿಫಾರಸು: ಪ್ರೋಟೋಕಾಲ್ (`typing.Protocol`).
- ಕಾರಣ: ಈ ಥರ್ಡ್-ಪಾರ್ಟಿ SDK ಗಳ ಸೋರ್ಸ್ ಕೋಡ್ ಅನ್ನು ನಿಮ್ಮ `Transaction` ಬೇಸ್ ಕ್ಲಾಸ್ನಿಂದ ಇನ್ಹೆರಿಟ್ ಮಾಡುವಂತೆ ನೀವು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಆದಾಗ್ಯೂ, ಅವುಗಳ ಪ್ರತಿಯೊಂದು ಟ್ರಾನ್ಸಾಕ್ಷನ್ ಆಬ್ಜೆಕ್ಟ್ಗಳಲ್ಲಿ `get_id()`, `get_amount()`, ಮತ್ತು `get_currency()` ನಂತಹ ಮೆಥಡ್ಗಳಿವೆ ಎಂದು ನಿಮಗೆ ತಿಳಿದಿದೆ, ಅವುಗಳು ಸ್ವಲ್ಪ ವಿಭಿನ್ನವಾಗಿ ಹೆಸರಿಸಲ್ಪಟ್ಟಿದ್ದರೂ ಸಹ. ಏಕೀಕೃತ ನೋಟವನ್ನು ರಚಿಸಲು ನೀವು ಅಡಾಪ್ಟರ್ ಪ್ಯಾಟರ್ನ್ ಜೊತೆಗೆ `TransactionProtocol` ಅನ್ನು ಬಳಸಬಹುದು. ಪ್ರೋಟೋಕಾಲ್ ನಿಮಗೆ ಬೇಕಾದ ಡೇಟಾದ *ಆಕಾರವನ್ನು* ವ್ಯಾಖ್ಯಾನಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ, ಯಾವುದೇ ಡೇಟಾ ಮೂಲದೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವ ಪ್ರೊಸೆಸಿಂಗ್ ಲಾಜಿಕ್ ಬರೆಯಲು ನಿಮಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ, ಎಲ್ಲಿಯವರೆಗೆ ಅದನ್ನು ಪ್ರೋಟೋಕಾಲ್ಗೆ ಹೊಂದಿಕೊಳ್ಳುವಂತೆ ಅಳವಡಿಸಬಹುದೋ.
ಸನ್ನಿವೇಶ 3: ದೊಡ್ಡ, ಏಕಶಿಲೆಯ ಲೆಗಸಿ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ರಿಫ್ಯಾಕ್ಟರಿಂಗ್ ಮಾಡುವುದು
ನೀವು ಲೆಗಸಿ ಮೊನೊಲಿತ್ ಅನ್ನು ಆಧುನಿಕ ಮೈಕ್ರೋಸರ್ವಿಸ್ಗಳಾಗಿ ವಿಭಜಿಸುವ ಕಾರ್ಯವನ್ನು ವಹಿಸಿಕೊಂಡಿದ್ದೀರಿ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕೋಡ್ಬೇಸ್ ಅವಲಂಬನೆಗಳ ಒಂದು ಗೋಜಲಿನ ಜಾಲವಾಗಿದೆ, ಮತ್ತು ನೀವು ಎಲ್ಲವನ್ನೂ ಒಂದೇ ಬಾರಿಗೆ ಪುನಃ ಬರೆಯದೆ ಸ್ಪಷ್ಟ ಗಡಿಗಳನ್ನು ಪರಿಚಯಿಸಬೇಕಾಗಿದೆ.
- ಶಿಫಾರಸು: ಒಂದು ಮಿಶ್ರಣ, ಆದರೆ ಪ್ರೋಟೋಕಾಲ್ಗಳ ಮೇಲೆ ಹೆಚ್ಚು ಒಲವು ತೋರಿ.
- ಕಾರಣ: ಪ್ರೋಟೋಕಾಲ್ಗಳು ಹಂತಹಂತವಾದ ರಿಫ್ಯಾಕ್ಟರಿಂಗ್ಗೆ ಒಂದು ಅಸಾಧಾರಣ ಸಾಧನವಾಗಿದೆ. ನೀವು `typing.Protocol` ಬಳಸಿ ಹೊಸ ಸೇವೆಗಳ ನಡುವಿನ ಆದರ್ಶ ಇಂಟರ್ಫೇಸ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸುವುದರೊಂದಿಗೆ ಪ್ರಾರಂಭಿಸಬಹುದು. ನಂತರ, ಕೋರ್ ಲೆಗಸಿ ಕೋಡ್ ಅನ್ನು ತಕ್ಷಣ ಬದಲಾಯಿಸದೆ, ಮೊನೊಲಿತ್ನ ಭಾಗಗಳನ್ನು ಈ ಪ್ರೋಟೋಕಾಲ್ಗಳಿಗೆ ಅನುಗುಣವಾಗಿ ಅಡಾಪ್ಟರ್ಗಳನ್ನು ಬರೆಯಬಹುದು. ಇದು ನಿಮಗೆ ಘಟಕಗಳನ್ನು ಹಂತಹಂತವಾಗಿ ಡಿಕಪಲ್ ಮಾಡಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಒಂದು ಘಟಕವು ಸಂಪೂರ್ಣವಾಗಿ ಡಿಕಪಲ್ ಆಗಿ ಕೇವಲ ಪ್ರೋಟೋಕಾಲ್ ಮೂಲಕ ಸಂವಹನ ನಡೆಸಿದಾಗ, ಅದನ್ನು ತನ್ನದೇ ಆದ ಸೇವೆಗೆ ಹೊರತೆಗೆಯಲು ಸಿದ್ಧವಾಗಿರುತ್ತದೆ. ನಂತರ, ಹೊಸ, ಸ್ವಚ್ಛ ಸೇವೆಗಳಲ್ಲಿ ಕೋರ್ ಮಾಡೆಲ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಲು ಫಾರ್ಮಲ್ ಎಬಿಸಿಗಳನ್ನು ಬಳಸಬಹುದು.
ತೀರ್ಮಾನ: ನಿಮ್ಮ ಕೋಡ್ನಲ್ಲಿ ಅಬ್ಸ್ಟ್ರಾಕ್ಷನ್ ಅನ್ನು ಹೆಣೆಯುವುದು
ಪೈಥಾನ್ನ ಅಬ್ಸ್ಟ್ರಾಕ್ಟ್ ಬೇಸ್ ಕ್ಲಾಸ್ಗಳು ಭಾಷೆಯ ಪ್ರಾಯೋಗಿಕ ವಿನ್ಯಾಸಕ್ಕೆ ಸಾಕ್ಷಿಯಾಗಿದೆ. ಅವು ಸಾಂಪ್ರದಾಯಿಕ ಆಬ್ಜೆಕ್ಟ್-ಓರಿಯೆಂಟೆಡ್ ಪ್ರೋಗ್ರಾಮಿಂಗ್ನ ರಚನಾತ್ಮಕ ಶಿಸ್ತು ಮತ್ತು ಡಕ್ ಟೈಪಿಂಗ್ನ ಡೈನಾಮಿಕ್ ನಮ್ಯತೆ ಎರಡನ್ನೂ ಗೌರವಿಸುವ ಅಬ್ಸ್ಟ್ರಾಕ್ಷನ್ಗಾಗಿ ಒಂದು ಅತ್ಯಾಧುನಿಕ ಟೂಲ್ಕಿಟ್ ಅನ್ನು ಒದಗಿಸುತ್ತವೆ.
ಒಂದು ಸೂಚ್ಯ ಒಪ್ಪಂದದಿಂದ ಔಪಚಾರಿಕ ಒಪ್ಪಂದದವರೆಗಿನ ಪ್ರಯಾಣವು ಬೆಳೆಯುತ್ತಿರುವ ಕೋಡ್ಬೇಸ್ನ ಸಂಕೇತವಾಗಿದೆ. ಎಬಿಸಿಗಳ ಎರಡು ತತ್ವಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವ ಮೂಲಕ, ನೀವು ಸ್ವಚ್ಛ, ಹೆಚ್ಚು ನಿರ್ವಹಿಸಬಲ್ಲ, ಮತ್ತು ಹೆಚ್ಚು ವಿಸ್ತರಿಸಬಹುದಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಕಾರಣವಾಗುವ ತಿಳುವಳಿಕೆಯುಳ್ಳ ವಾಸ್ತುಶಿಲ್ಪದ ನಿರ್ಧಾರಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಹುದು.
ಪ್ರಮುಖ ಅಂಶಗಳನ್ನು ಸಂಕ್ಷಿಪ್ತಗೊಳಿಸಲು:
- ಫಾರ್ಮಲ್ ಇಂಟರ್ಫೇಸ್ ವಿನ್ಯಾಸ (ನಾಮಿನಲ್ ಟೈಪಿಂಗ್): ನಿಮಗೆ ಸ್ಪಷ್ಟ, ಅಸ್ಪಷ್ಟವಲ್ಲದ, ಮತ್ತು ಕಂಡುಹಿಡಿಯಬಹುದಾದ ಒಪ್ಪಂದದ ಅಗತ್ಯವಿದ್ದಾಗ ನೇರ ಇನ್ಹೆರಿಟೆನ್ಸ್ನೊಂದಿಗೆ `abc.ABC` ಬಳಸಿ. ಇದು ಫ್ರೇಮ್ವರ್ಕ್ಗಳು, ಪ್ಲಗಿನ್ ಸಿಸ್ಟಮ್ಗಳು ಮತ್ತು ನೀವು ಕ್ಲಾಸ್ ಶ್ರೇಣಿಯನ್ನು ನಿಯಂತ್ರಿಸುವ ಸಂದರ್ಭಗಳಿಗೆ ಸೂಕ್ತವಾಗಿದೆ. ಇದು ಘೋಷಣೆಯ ಮೂಲಕ ಒಂದು ಕ್ಲಾಸ್ ಏನು ಆಗಿದೆ ಎಂಬುದರ ಬಗ್ಗೆ.
- ಪ್ರೋಟೋಕಾಲ್ ಇಂಪ್ಲಿಮೆಂಟೇಶನ್ (ಸ್ಟ್ರಕ್ಚರಲ್ ಟೈಪಿಂಗ್): ನಿಮಗೆ ನಮ್ಯತೆ, ಡಿಕಪ್ಲಿಂಗ್ ಮತ್ತು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕೋಡ್ ಅನ್ನು ಅಳವಡಿಸಿಕೊಳ್ಳುವ ಸಾಮರ್ಥ್ಯ ಬೇಕಾದಾಗ `typing.Protocol` ಬಳಸಿ. ಇದು ಬಾಹ್ಯ ಲೈಬ್ರರಿಗಳೊಂದಿಗೆ ಕೆಲಸ ಮಾಡಲು, ಲೆಗಸಿ ಸಿಸ್ಟಮ್ಗಳನ್ನು ರಿಫ್ಯಾಕ್ಟರಿಂಗ್ ಮಾಡಲು ಮತ್ತು ನಡವಳಿಕೆಯ ಪಾಲಿಮಾರ್ಫಿಸಂಗಾಗಿ ವಿನ್ಯಾಸಗೊಳಿಸಲು ಪರಿಪೂರ್ಣವಾಗಿದೆ. ಇದು ಅದರ ರಚನೆಯಿಂದ ಒಂದು ಕ್ಲಾಸ್ ಏನು ಮಾಡಬಲ್ಲದು ಎಂಬುದರ ಬಗ್ಗೆ.
ಇಂಟರ್ಫೇಸ್ ಮತ್ತು ಪ್ರೋಟೋಕಾಲ್ ನಡುವಿನ ಆಯ್ಕೆಯು ಕೇವಲ ತಾಂತ್ರಿಕ ವಿವರವಲ್ಲ; ಇದು ನಿಮ್ಮ ಸಾಫ್ಟ್ವೇರ್ ಹೇಗೆ ವಿಕಸನಗೊಳ್ಳುತ್ತದೆ ಎಂಬುದನ್ನು ರೂಪಿಸುವ ಒಂದು ಮೂಲಭೂತ ವಿನ್ಯಾಸ ನಿರ್ಧಾರವಾಗಿದೆ. ಎರಡರಲ್ಲೂ ಪಾಂಡಿತ್ಯ ಸಾಧಿಸುವ ಮೂಲಕ, ನೀವು ಶಕ್ತಿಶಾಲಿ ಮತ್ತು ದಕ್ಷ ಮಾತ್ರವಲ್ಲದೆ, ಬದಲಾವಣೆಯ ಮುಖಾಂತರ ಸೊಗಸಾದ ಮತ್ತು ಸ್ಥಿತಿಸ್ಥಾಪಕವಾಗಿರುವ ಪೈಥಾನ್ ಕೋಡ್ ಬರೆಯಲು ನಿಮ್ಮನ್ನು ಸಜ್ಜುಗೊಳಿಸುತ್ತೀರಿ.