Functions, Modules, Packages: কোড যখন notebook থেকে বড় হয়

flagship project-এর প্রথম কাঠামো তৈরি (Series 02, Episode 03)

🟢 BEGINNER Series 02 — AI Engineer-দের জন্য Python Episode 03 / 09

📑 এই পর্বে যা যা আছে

🧩 ১. গল্প: Rahim-এর copy-paste দুর্দশা

Rahim তার job-analyzer script-এ একই "skill খোঁজার" কোড ৫ জায়গায় copy-paste করেছে। এখন skill খোঁজার নিয়ম একটু বদলাতে গিয়ে তাকে ৫ জায়গায় বদলাতে হচ্ছে — একটা জায়গা মিস করলে বাগ।

Arif (ML engineer) দেখে বলল:

"এই সমস্যাটা প্রতিটা junior-এর হয়। Notebook-এ সব একসাথে লিখলে প্রথমে দ্রুত মনে হয়, কিন্তু project বড় হলে maintain করা দুঃস্বপ্ন। সমাধান তিনটা শব্দে: function, module, package। এগুলোই code-কে notebook থেকে software-এ রূপান্তর করে।"

২. আসল সমস্যা: একই কোড বারবার

AI/ML-এ একটা কাজ বারবার লাগে — data পরিষ্কার করা, skill বের করা, metric হিসাব করা। প্রতিবার নতুন করে লিখলে: (১) সময় নষ্ট, (২) bug ছড়ায়, (৩) কোড পড়া কঠিন। এর সমাধান — একবার লিখে বারবার ব্যবহার করা, অর্থাৎ function

♻️ ৩. function কেন — DRY নীতি

DRY = Don't Repeat Yourself। একটা কাজ একবার function-এ লিখুন, তারপর যতবার লাগে call করুন। নিয়ম বদলালে একটাই জায়গা বদলাবেন।

function হলো একটা নামওয়ালা কাজের ব্লক: কিছু input (argument) নেয়, কিছু কাজ করে, একটা output (return) দেয়। ML pipeline আসলে ছোট ছোট function-এর একটা chain।

🎯 ৪. তিন লেভেলে বোঝা: function, module, package

Level 1 — সহজ intuition:
function = একটা রেসিপি (একটা কাজ)। module = একটা রেসিপি বই (এক file-এ কয়েকটা রেসিপি)। package = একটা রান্নার লাইব্রেরি (কয়েকটা বই একসাথে ফোল্ডারে)।
Level 2 — technical ভাবে:
function = def দিয়ে সংজ্ঞায়িত reusable block। module = একটা .py file, যেখানে অনেক function/class থাকে। package = এমন একটা folder যাতে module থাকে (এবং সাধারণত __init__.py)।
Level 3 — AI Engineer-এর দৃষ্টিকোণ:
production project-এ কোড আলাদা module-এ ভাগ থাকে: data.py (data load), features.py (feature বানানো), model.py (model), api.py (serving)। scikit-learn, PyTorch নিজেরাও বিশাল package — আপনি রোজ from sklearn.linear_model import ... লেখেন।

🔧 ৫. function লেখা: argument, default, return

def count_skill(job_descriptions, skill): """একটা skill কতটি job-এ আছে তা গোনে।""" count = 0 for jd in job_descriptions: if skill.lower() in jd.lower(): count += 1 return count def skill_share(job_descriptions, skill, as_percent=True): """skill কত অংশ job-এ আছে। as_percent=False দিলে ভগ্নাংশ।""" n = len(job_descriptions) if n == 0: return 0.0 share = count_skill(job_descriptions, skill) / n return share * 100 if as_percent else share jds = [ "Python and ML required", "Python, FastAPI backend", "SQL data analyst", ] print(count_skill(jds, "python")) # 2 print(skill_share(jds, "python")) # 66.66... print(skill_share(jds, "python", False)) # 0.666...

যা লক্ষ্য করবেন: as_percent=True হলো default argument — না দিলে percent আসে। একটা function আরেকটাকে call করছে (skill_share ভেতরে count_skill) — এভাবেই ছোট function জোড়া দিয়ে বড় কাজ হয়।

🖼️ ৬. Visual: notebook থেকে package-এ যাত্রা

পর্যায় ১: সব এক file-এ (notebook style) analyzer.py → data + skill + report সব একসাথে (messy) পর্যায় ২: function-এ ভাগ analyzer.py → load_jobs(), count_skill(), make_report() পর্যায় ৩: module-এ ভাগ (একাধিক file) data.py → load_jobs() skills.py → count_skill(), skill_share() report.py → make_report() পর্যায় ৪: package (folder) career_assistant/ __init__.py data.py skills.py report.py

📄 ৭. module: কোড আলাদা file-এ ভাগ করা

# file: skills.py def count_skill(job_descriptions, skill): return sum(skill.lower() in jd.lower() for jd in job_descriptions) # file: main.py (অন্য file থেকে import) from skills import count_skill jds = ["Python ML", "SQL only", "Python FastAPI"] print(count_skill(jds, "python")) # 2

কেন module? একই file হাজার লাইন হলে কেউ পড়তে পারে না। বিষয় অনুযায়ী file-এ ভাগ করলে team-এর সবাই দ্রুত খুঁজে পায়, আর একটা অংশ বদলালে বাকিটা নিরাপদ থাকে।

📦 ৮. package: folder + __init__.py

অনেকগুলো module একটা folder-এ রাখলে সেটা package হয়। folder-এ একটা (খালি হলেও চলে) __init__.py থাকলে Python বোঝে এটা একটা package।

career_assistant/ __init__.py # folder-কে package বানায় (খালি হলেও চলে) data.py # def load_jobs(path): ... skills.py # def count_skill(...), skill_share(...) report.py # def make_report(...) # ব্যবহার (project root থেকে): # from career_assistant.skills import count_skill
মনে রাখুন: import path সবসময় আপনি কোথা থেকে Python চালাচ্ছেন তার ওপর নির্ভর করে। junior-দের সবচেয়ে বড় বিভ্রান্তি এখানেই — তাই project root থেকে চালানোর অভ্যাস করুন।

💻 ৯. Code: flagship V1-এর প্রথম কাঠামো

এবার আমরা Bangladesh Tech Career Assistant-এর V1 কাঠামো বানাই।

# career_assistant/data.py def load_jobs(): """আপাতত hard-coded; পরে file/DB থেকে আসবে (E06)।""" return [ {"title": "ML Engineer", "text": "Python, ML, SQL"}, {"title": "Backend Dev", "text": "Python, FastAPI"}, {"title": "Data Analyst", "text": "SQL, Excel"}, ] # career_assistant/skills.py def count_skill(jobs, skill): return sum(skill.lower() in j["text"].lower() for j in jobs) # main.py from career_assistant.data import load_jobs from career_assistant.skills import count_skill def main(): jobs = load_jobs() for skill in ["python", "sql", "fastapi"]: c = count_skill(jobs, skill) print(f"{skill:10s}: {c}/{len(jobs)} jobs") if __name__ == "__main__": main()

if __name__ == "__main__": মানে — এই file সরাসরি চালালে main() চলবে, কিন্তু import করলে চলবে না। এটা Python-এর একটা গুরুত্বপূর্ণ অভ্যাস।

🧪 ১০. Experiment: import ও reuse

উপরের কাঠামো বানিয়ে python3 main.py চালান। তারপর skills.py-তে একটা নতুন function top_skill(jobs, candidates) যোগ করুন যা সবচেয়ে বেশিবার আসা skill ফেরত দেয় — এবং main.py-তে import করে ব্যবহার করুন। লক্ষ্য করুন: data.py একটুও বদলাতে হলো না।

👷 ১১. AI Engineer-এর দৃষ্টিকোণ

💼 ১২. Boss Question

Boss: "একটা কাজ তো হয়েই গেছে, আবার function-module-package-এ ভাগ করে সময় নষ্ট কেন?"

উত্তর: কারণ ৩ মাস পরে যখন নতুন feature বা bug fix লাগবে, ভালো-ভাগ করা কোডে সেটা ঘণ্টার কাজ; জগাখিচুড়ি কোডে সপ্তাহের কাজ। ভালো structure = দ্রুত পরিবর্তন, কম bug, নতুন developer দ্রুত যোগ দিতে পারে — সব সরাসরি খরচ ও সময় বাঁচায়।

🔎 ১৩. Job Requirement Decoder: "Clean, modular, maintainable Python code"

প্রশ্নউত্তর
এর মানে কী?কোড function/module-এ ভাগ করা, DRY, পড়ার মতো — এলোমেলো এক-file script নয়।
কোম্পানি কেন চায়?team-এ অনেকে একসাথে কাজ করে; maintainable কোড ছাড়া project টিকে না।
কোন সমস্যা সমাধান করে?copy-paste bug, বড় file, কঠিন debug, ধীর onboarding।
junior-এর কী জানা লাগে?function লেখা, module-এ ভাগ, import, __main__ guard।
এখনই কী master লাগে না?packaging/publish (PyPI), entry points, namespace package internals।
GitHub-এ কীভাবে দেখাবেন?flagship project-এর পরিষ্কার folder structure + ছোট function।
Interview-তে কী?"module vs package?", "__name__ == '__main__' কেন?", "DRY মানে?"

⚠️ ১৪. সাধারণ ভুল

ভুল ১: সব কোড এক file-এ — ঠিক: বিষয় অনুযায়ী module-এ ভাগ।

ভুল ২: function-এ mutable default (def f(x=[])) — ঠিক: def f(x=None), ভেতরে x = x or []

ভুল ৩: একটা function-এ ১০টা কাজ — ঠিক: এক function = এক দায়িত্ব।

ভুল ৪: from module import *ঠিক: স্পষ্টভাবে যা লাগে তাই import করুন।

🎤 ১৫. Interview Prep

প্রশ্ন ১: module আর package-এর পার্থক্য?
উত্তর: module একটা .py file; package একটা folder যাতে module থাকে (__init__.py সহ)।

প্রশ্ন ২: if __name__ == "__main__": কেন লাগে?
উত্তর: যাতে file সরাসরি চালালে code চলে, কিন্তু import করলে না চলে।

প্রশ্ন ৩: mutable default argument সমস্যা কী?
উত্তর: default একবারই তৈরি হয়, তাই সব call একই object share করে — bug হয়।

প্রশ্ন ৪: DRY মানে?
উত্তর: Don't Repeat Yourself — একই logic বারবার না লিখে function-এ রাখা।

✍️ ১৬. হাতে-কলমে (Mini Exercise)

১. career_assistant/ package বানান data.py, skills.py সহ।
২. skills.py-তে most_common_skill(jobs, candidates) function লিখুন।
৩. main.py থেকে import করে চালান।
৪. একই function-কে দুবার call করে দেখান — কোড repeat করলেন না, শুধু call করলেন।

🚀 ১৭. Project Connection

আজ আমরা flagship V1-এর কঙ্কাল বানালাম: career_assistant package, ভেতরে dataskills module। পরের episode-গুলোতে এই package-এ OOP (E04), file/JSON loading (E06), testing (E08) যোগ হবে, আর E09-তে GitHub-এ publish হবে।

📌 ১৮. সারসংক্ষেপ ও পরবর্তী পর্ব

✓ function = reusable কাজ; DRY নীতি bug কমায়
✓ module = এক .py file; package = module-ভরা folder (__init__.py)
__main__ guard দিয়ে file চালানো vs import আলাদা করা যায়
✓ flagship V1-এর প্রথম package structure দাঁড়াল
পরবর্তী Episode (S02E04): "OOP for ML: Class দিয়ে কেন model, dataset, pipeline লেখা হয়" — কেন scikit-learn আর PyTorch পুরোটাই class-based, আর আমরা কীভাবে একটা JobPost class বানাব।
© 2025 Sheikh Thanbir Alam. All Rights Reserved. thanbirtamim.github.io
এই লেখা মূল লেখকের সম্পত্তি — লিখিত অনুমতি ছাড়া কপি করে অন্য কোনো ওয়েবসাইট, ব্লগ, বই বা প্ল্যাটফর্মে প্রকাশ/বিতরণ করা কঠোরভাবে নিষিদ্ধ। Content may not be copied or republished without permission.