সরাসরি পর্বে যান
পর্ব ৬৩ · ৭০-এর মধ্যে · মডিউল ১০

দলগত কাজ আর open source — documentation, communication আর software license

Team Collaboration and Open Source — Documentation, Communication and Software Licenses

Taught in Bangla, this lesson covers how software teams work: feature and component teams, Team Topologies, Tuckman stages and psychological safety, asynchronous communication and written decisions, Diátaxis documentation, README and CONTRIBUTING files, computing a bus factor from commit authors, contributing to open source, CLA versus DCO, and permissive versus copyleft licenses, compatibility, SPDX and license scans.

এই পর্বে যা শিখবেন

  • দল সাজানোর প্রধান উপায়গুলো, Team Topologies-এর চার ধরন আর তিনটি interaction mode
  • দলের বেড়ে ওঠা, psychological safety, দ্বিমত মেটানো আর দূর থেকে ভিন্ন time zone-এ কাজের অভ্যাস
  • Diátaxis, README, CONTRIBUTING, API ও architecture-এর নথি আর onboarding — docs-as-code ধারায়
  • Commit-এর লেখক থেকে bus factor হিসাব, আর জ্ঞান ছড়ানোর কৌশল
  • Open source-এ অবদান রাখার পূর্ণ পথ, governance, CLA বনাম DCO আর code of conduct
  • প্রধান software license, license compatibility-র মূল নিয়ম, SPDX, NOTICE ফাইল আর dependency-র license scan

১ · দলের গঠন — feature team, component team আর Team Topologies

পর্ব ১-এ (Software engineering কী) দেখেছেন, n জনের দলে communication path n(n−1)/2টি, আর Conway's law বলে system-এর আকার দলের যোগাযোগের আকার নেয়। এই পর্বে প্রশ্ন হলো: তাহলে দল সাজাবেন কীভাবে, দলের ভেতরে আর দলের মধ্যে কথা বলবেন কীভাবে, আর দলের বাইরের পৃথিবীর — open source-এর — সাথে কোন নিয়মে কোড ভাগ করবেন।

একটি বিয়েবাড়ির আয়োজন ভাবুন। এক উপায়: রান্না, সাজসজ্জা, অতিথি আপ্যায়ন — প্রতিটির আলাদা দল; প্রতিটি অতিথির অভিজ্ঞতা তিন দলের হাত ঘুরে তৈরি হয়। আরেক উপায়: প্রতিটি টেবিলের একটি দল, যারা সেই টেবিলের খাবার, পানি আর আপ্যায়ন — সব নিজেরাই দেখে। প্রথমটি দক্ষতা ধরে ভাগ, দ্বিতীয়টি ফল ধরে ভাগ। Software দলেও ঠিক এই দুই পথ।

Component team

একটি স্তর বা অংশের দায়িত্বে: “database দল”, “Android দল”। গভীর দক্ষতা জমে, কিন্তু একটি ছোট feature-ও কয়েক দলের সারিতে অপেক্ষা করে — হাতবদল (handoff) বাড়ে।

component team

Feature team

Front-end থেকে database পর্যন্ত সব দক্ষতা এক দলে; একটি ব্যবহারকারী-দৃশ্যমান feature শুরু থেকে শেষ পর্যন্ত এক দল বানায়। হাতবদল কমে, কিন্তু একই কোডে বহু দল হাত দেয় — review আর নিয়মের দরকার বাড়ে।

feature team

এই দুই ভাগের আলোচনা Large-Scale Scrum (LeSS) ঘরানার লেখায় — Craig Larman আর Bas Vodde-র বইয়ে — বিস্তারিত পাবেন; তাঁরা feature team-এর পক্ষে জোর যুক্তি দেন। বাস্তবে অনেক প্রতিষ্ঠান মিশ্র পথ নেয়।

Team Topologies — চার ধরনের দল, তিন রকম মেলামেশা

Matthew Skelton আর Manuel Pais-এর বই Team Topologies (২০১৯) একটি জনপ্রিয় শব্দভান্ডার দিয়েছে। মূল কথা: প্রতিটি দলের মাথায় কতটা জিনিস ধরে — cognitive load — তার একটি সীমা আছে; দলের দায়িত্ব সেই সীমার মধ্যে রাখুন। বইয়ের প্রস্তাবিত চার ধরন:

ধরনকাজকাল্পনিক অনলাইন বাজার অ্যাপে উদাহরণ
Stream-alignedব্যবসার একটি ধারার (stream) কাজ শুরু থেকে শেষ পর্যন্ত; বেশিরভাগ দল এই ধরনের হওয়ার কথা“checkout দল”, “বিক্রেতার dashboard দল”
Platformভেতরের সেবা বানায় যা অন্য দল নিজে থেকে (self-service) ব্যবহার করেdeployment pipeline, log আর monitoring-এর সেবা
Enablingবিশেষজ্ঞ দল যারা অন্য দলকে নতুন দক্ষতা শেখায়, তারপর সরে যায়কয়েক সপ্তাহ checkout দলের সাথে বসে test automation শেখানো
Complicated-subsystemগভীর বিশেষজ্ঞ জ্ঞান লাগে এমন একটি অংশদাম ঠিক করার গাণিতিক মডেল, ছবি থেকে পণ্য চেনার engine

দলগুলো কীভাবে মেলামেশা করে, তারও তিনটি নাম আছে: collaboration (একটি নির্দিষ্ট সময়ের জন্য পাশাপাশি কাজ), X-as-a-Service (একটি দল সেবা দেয়, অন্যটি নথি দেখে নিজে ব্যবহার করে, কম কথায়) আর facilitating (একটি দল আরেকটিকে শেখায়)। নিচের ছবিতে এগুলো একসাথে:

Team Topologies — চার ধরনের দল আর তাদের মেলামেশা

Stream-aligned teams consume a platform as a service; enabling teams facilitate; a complicated-subsystem team offers a service

Team Topologies: stream-aligned, platform, enabling আর complicated-subsystem দল Checkout দল বিক্রেতা দল ডেলিভারি দল Platform দল stream-aligned stream-aligned stream-aligned pipeline · log · monitoring (self-service) দামের মডেল জটিল অংশ Enabling দল গ্রাহক বিক্রেতা X-as-a-Service ড্যাশ তীর = facilitating · কঠিন তীর = সেবা ব্যবহার
ছবি ৬৩.১ — নীল stream-aligned দলগুলোই সরাসরি গ্রাহক বা বিক্রেতার কাছে মূল্য পৌঁছায়। সবুজ platform তাদের সেবা দেয়, হলুদ enabling দল সাময়িকভাবে শেখায়, বেগুনি দল একটি কঠিন অংশ সামলায়। নাম আর চার ভাগ Skelton ও Pais (২০১৯)-এর; এটি একটি চিন্তার কাঠামো, প্রমাণিত সূত্র নয়।

দলের সীমারেখা ঠিক করা মানে architecture-এর সীমারেখাও ঠিক করা — Conway's law উল্টো করে ব্যবহারের এই চিন্তাকে বলে inverse Conway maneuver (পর্ব ৩৮-এ ছুঁয়ে গেছেন)। Microservice-এর সীমা আর দলের সম্পর্ক নিয়ে আরও পড়ুন System Design কোর্সের Microservices পর্বে।

২ · দল কীভাবে বেড়ে ওঠে — Tuckman, psychological safety আর দ্বিমত

১৯৬৫ সালে মনোবিজ্ঞানী Bruce Tuckman ছোট দলের ওপর আগের গবেষণা পর্যালোচনা করে চারটি ধাপের একটি মডেল দেন (“Developmental sequence in small groups”, Psychological Bulletin); ১৯৭৭ সালে Mary Ann Jensen-এর সাথে পঞ্চম ধাপ যোগ করেন। এই Tuckman model মোটা দাগের বর্ণনা — প্রতিটি দল এই ক্রম মেনে চলে বা ধাপগুলো স্পষ্ট আলাদা, এমন নয়; নতুন সদস্য এলে দল আবার আগের ধাপে ফিরতেও পারে। নিচে একটি বিশ্ববিদ্যালয়ের ফলাফল পোর্টালের কাল্পনিক দল ধরে দেখুন:

  1. Forming১৯৬৫ভদ্র, সাবধানী
  2. Storming১৯৬৫মতের ঘর্ষণ
  3. Norming১৯৬৫নিয়ম তৈরি
  4. Performing১৯৬৫নিজে চলে
  5. Adjourning১৯৭৭বিদায়
  1. Forming. পাঁচজন নতুন দল, ফলাফল পোর্টাল বানাতে হবে। সবাই ভদ্র, কেউ কারও কোডে মন্তব্য করতে চান না, আর প্রশ্ন জমে থাকে। এখানে দরকার স্পষ্ট লক্ষ্য, কে কী করবেন, আর কাজের প্রথম ছোট নিয়ম — যেমন PR কত বড় হবে।
  2. Storming. প্রথম মতবিরোধ: কেউ চান GPA হিসাব database-এ, কেউ চান কোডে। Review-এর মন্তব্য কড়া লাগে, দুজনের মধ্যে চাপা বিরক্তি। এই ধাপ এড়ানো যায় না; লক্ষ্য হলো দ্বিমত ব্যক্তি নিয়ে নয়, প্রস্তাব নিয়ে রাখা।
  3. Norming. দল লিখে নেয়: সিদ্ধান্ত ADR-এ, review-এর মন্তব্যে লেবেল, দৈনিক আলাপ ১৫ মিনিট। মানুষ একে অপরের শক্তি চেনেন। লিখিত নিয়ম ভবিষ্যতের নতুন সদস্যের জন্যও।
  4. Performing. ফলাফল প্রকাশের চাপের সপ্তাহে দল নিজেরাই কাজ ভাগ করে, সমস্যা আগে বলে, একে অপরের PR দ্রুত দেখে। নেতার ভূমিকা এখন বাধা সরানো, আদেশ দেওয়া নয়।
  5. Adjourning. Project শেষ, দল ভেঙে অন্য কাজে যাচ্ছে। শেষ কাজ: হস্তান্তরের নথি, কে কোন অংশ দেখবেন, আর একটি retrospective (পর্ব ৫)। এটি না করলে পরের দল শূন্য থেকে শুরু করে।

Psychological safety — প্রশ্ন করার নিরাপত্তা

Harvard-এর গবেষক Amy Edmondson ১৯৯৯ সালে (“Psychological Safety and Learning Behavior in Work Teams”, Administrative Science Quarterly) psychological safety-কে দলের একটি যৌথ বিশ্বাস হিসেবে মাপেন: এখানে ঝুঁকি নিয়ে কথা বললে — প্রশ্ন, ভুল স্বীকার, দ্বিমত — অপমান বা শাস্তি আসবে না। তাঁর গবেষণায় এমন দলে শেখার আচরণ বেশি দেখা গিয়েছিল। পরে Google-এর ভেতরের গবেষণা Project Aristotle (ফল প্রকাশ্যে আসে ২০১৫-২০১৬ সালের দিকে, re:Work সাইট আর সংবাদমাধ্যমে) কার্যকর দলের কয়েকটি বৈশিষ্ট্যের মধ্যে psychological safety-কে সবচেয়ে গুরুত্বপূর্ণ বলে জানায় — তবে সেটি এক প্রতিষ্ঠানের নিজের তথ্যে, নিজের সংজ্ঞায় করা বিশ্লেষণ, তাই সব দলে একই ফল ধরে নেবেন না।

মূল ধারণা

Psychological safety মানে “সবাই সবসময় একমত” বা “মান কম রাখা” নয়। উল্টো: উঁচু মান আর উঁচু নিরাপত্তা একসাথে থাকলেই মানুষ কঠিন কথা সময়মতো বলেন। ছোট অভ্যাস যা সাহায্য করে: নেতা নিজের ভুল আগে বলেন; সভায় সবচেয়ে নতুন সদস্যকে আগে মত দিতে বলা হয়; ঘটনার পরে blameless পর্যালোচনা; review-এ মানুষ নয়, কোড নিয়ে কথা (পর্ব ৪৪-এর Code review-এ মন্তব্যের ভাষা দেখেছেন)।

দ্বিমত মেটানো — কয়েকটি মৌলিক কৌশল

  • স্বার্থ দেখুন, অবস্থান নয়: “আমি PostgreSQL চাই” একটি অবস্থান; “আমাদের join-ভারী report লাগে” একটি স্বার্থ। স্বার্থ লিখে ফেললে প্রায়ই তৃতীয় সমাধান বেরোয় — Fisher আর Ury-র Getting to Yes (১৯৮১) এই কৌশলের পরিচিত উৎস।
  • মাপকাঠি আগে ঠিক করুন: কোন quality attribute বেশি জরুরি (পর্ব ৩), তা আগে মেনে নিলে বিকল্প বাছাই সহজ।
  • সিদ্ধান্তের মালিক আর সময়সীমা: কে শেষ কথা বলবেন, কবে — আগে জানা থাকলে তর্ক অনন্তকাল চলে না। “Disagree and commit”: দ্বিমত লিখে রেখে সিদ্ধান্ত মেনে কাজ করা।
  • লিখিত চ্যানেল থেকে কথায় যান: তিনবারের বেশি মন্তব্য চালাচালি হলে একটি ছোট call, তারপর ফলাফল আবার লিখে রাখুন।
  • ব্যক্তিগত দ্বন্দ্ব আলাদা পথে: অসম্মান বা হয়রানি “দ্বিমত” নয় — সেটি code of conduct আর ব্যবস্থাপনার বিষয় (অংশ ৬)।

৩ · যোগাযোগ — synchronous বনাম asynchronous, সভা আর লিখিত সিদ্ধান্ত

দলের যোগাযোগ দুই রকম। Synchronous: সবাই একই সময়ে উপস্থিত — সভা, call, পাশের টেবিলে প্রশ্ন। Asynchronous: লেখা থাকে, যে যার সময়ে পড়েন আর উত্তর দেন — issue, PR-এর মন্তব্য, নথি, chat-এর thread.

দিকSynchronousAsynchronous
ভালো কাজেজটিল দ্বিমত, আবেগের বিষয়, দ্রুত brainstorming, জরুরি incidentঅবস্থা জানানো, প্রস্তাব, review, সিদ্ধান্তের রেকর্ড
খরচসবার মনোযোগ একসাথে ভাঙে; time zone আটকায়উত্তর পেতে দেরি; লেখার দক্ষতা লাগে
স্মৃতিলিখে না রাখলে হারায়নিজে থেকেই খোঁজা যায়, নতুনরা পরে পড়তে পারেন

সভা হলে — agenda, সময় আর লিখিত ফল

একটি ভালো সভার তিনটি অংশ: আগে পাঠানো agenda (কী সিদ্ধান্ত চাই, কী পড়ে আসতে হবে), নির্দিষ্ট সময় আর একজন সঞ্চালক, আর শেষে লিখিত ফল — সিদ্ধান্ত, কে কী করবেন, কবে। রেলের সময়সূচির মতো: ট্রেন কখন ছাড়বে আগে জানা, আর না জানলে সবাই প্ল্যাটফর্মে বসে থাকেন।

সভা: ফলাফল পোর্টাল — GPA হিসাব কোথায় হবে
সময়: ৩০ মিনিট · উপস্থিত: নীলা (সঞ্চালক), করিম, সুমি, তানভীর
আগে পড়ার: docs/adr/0007-gpa-calculation.md (খসড়া)

সিদ্ধান্ত: GPA হিসাব application code-এ, database-এ নয়
কারণ: নিয়ম বছর বছর বদলায়; unit test লেখা সহজ
দ্বিমত: করিম — report-এর গতি নিয়ে চিন্তা; ৩ মাস পরে মেপে দেখা হবে
কাজ: সুমি — ADR 0007 চূড়ান্ত করা (বৃহস্পতিবার)
      তানভীর — GPA module-এর unit test (রবিবার)

খেয়াল করুন, সিদ্ধান্তের বিস্তারিত সভার নোটে নয়, একটি ADR-এ যাচ্ছে (ADR পর্ব ৩৮-এ, Software architecture). সভার নোট শুধু বলে কোথায় খুঁজবেন।

দূর থেকে, হাইব্রিড আর ভিন্ন time zone-এ

বাংলাদেশের অনেক developer এখন বিদেশি দল বা ক্লায়েন্টের সাথে দূর থেকে কাজ করেন। বাংলাদেশের সময় UTC+6, আর বর্তমানে এখানে daylight saving time নেই — কিন্তু ইউরোপ আর উত্তর আমেরিকায় আছে, এবং দুই অঞ্চলে সময় বদলানোর তারিখও আলাদা। একটি হিসাব: ঢাকায় সকাল ১০টা–সন্ধ্যা ৬টা মানে UTC 04:00–12:00; শীতকালে Berlin-এ (UTC+1) সকাল ৯টা–বিকেল ৫টা মানে UTC 08:00–16:00. দুটি মেলালে একসাথে কাজের সময় UTC 08:00–12:00, অর্থাৎ ৪ ঘণ্টা — ঢাকায় দুপুর ২টা থেকে সন্ধ্যা ৬টা। গ্রীষ্মে Berlin UTC+2 হলে মিলিত সময় বেড়ে ৫ ঘণ্টা। অনুশীলন ৪-এ তৃতীয় একটি শহর যোগ করে নিজে হিসাব করবেন।

  • লেখার সংস্কৃতি (writing culture): প্রস্তাব আগে লেখায়, তারপর আলোচনা। লেখা মানুষকে নিজের চিন্তা গুছাতে বাধ্য করে, আর যিনি সভায় ছিলেন না তিনিও অংশ নিতে পারেন। কিছু প্রতিষ্ঠান তাদের handbook প্রকাশ্যে রাখে, যা থেকে এই ধরনের নিয়ম দেখা যায়।
  • উত্তরের প্রত্যাশা লিখে রাখুন: “PR review ১ কর্মদিবসে, জরুরি হলে call” — যাতে নীরবতাকে কেউ অবহেলা না ভাবেন।
  • একটি প্রশ্নে পুরো প্রসঙ্গ: “হাই, আছেন?” লিখে অপেক্ষা নয়; কী চাইছেন, কী চেষ্টা করেছেন, কী error — একবারে।
  • হাইব্রিড সভায় সবাই নিজের যন্ত্র থেকে যোগ দিলে দূরের মানুষ পিছিয়ে পড়েন না; সিদ্ধান্ত লেখা হয় সবার দেখা নথিতে।

৪ · Documentation — Diátaxis, README, CONTRIBUTING আর docs-as-code

সব নথি এক রকম নয়। Daniele Procida-র Diátaxis কাঠামো (আগে “Divio documentation system” নামে পরিচিত ছিল) ব্যবহারকারীর প্রয়োজন ধরে নথিকে চার ভাগ করে। কাঠামোটি জনপ্রিয় হলেও একমাত্র পথ নয় — তবু ভাগগুলো মাথায় রাখলে একটি পাতায় সব মিশিয়ে ফেলার ভুল কমে।

🎓 Tutorial

শেখার জন্য: নতুন মানুষকে হাত ধরে একটি ছোট সফল কাজ করানো। “প্রথম order তৈরি করুন — ১০ মিনিটে”।

🛠️ How-to guide

কাজের জন্য: যিনি জানেন কী চান, তাঁকে নির্দিষ্ট লক্ষ্যে পৌঁছানো। “bKash-এর মতো একটি নতুন payment gateway যোগ করবেন কীভাবে”।

📖 Reference

তথ্যের জন্য: শুষ্ক, সম্পূর্ণ, নির্ভুল। প্রতিটি API endpoint, parameter, error code.

💡 Explanation

বোঝার জন্য: কেন এমন নকশা, কোন বিকল্প বাদ গেল, পেছনের ধারণা। ADR আর architecture নথি এখানে পড়ে।

প্রতিটি repository-র মৌলিক নথি

ফাইলকার জন্যভেতরে যা থাকে
README.mdপ্রথম দর্শনার্থীনাম, এক-দুই বাক্যে কী আর কেন, install, ছোট usage উদাহরণ, অবদানের পথ, license
CONTRIBUTING.mdসম্ভাব্য অবদানকারীdev environment, test চালানো, branch আর commit-এর নিয়ম, PR-এর প্রক্রিয়া, DCO/CLA
CODE_OF_CONDUCT.mdসবাইআচরণের প্রত্যাশা, অভিযোগের পথ, কে ব্যবস্থা নেবেন
LICENSE (আর দরকারে NOTICE)ব্যবহারকারী, আইনি দলপূর্ণ license-এর লেখা (অংশ ৭)
CHANGELOG.mdব্যবহারকারীversion ধরে পরিবর্তন (পর্ব ১৮)
SECURITY.mdনিরাপত্তা-গবেষকদুর্বলতা গোপনে জানানোর পথ
docs/দল আর ব্যবহারকারীDiátaxis-এর চার ভাগ, ADR, onboarding-এর নির্দেশিকা

এই ফাইলগুলো সাধারণ লেখার ফাইল — Markdown — কোডের পাশে একই Git repository-তে। এটাই docs as code: নথি বদলায় PR দিয়ে, review হয়, CI-তে ভাঙা link আর বানান যাচাই হয়, আর version-এর সাথে tag হয় — v2.0-এর কোড checkout করলে v2.0-এর নথিই পাবেন। Code-এর আচরণ বদলানো PR-এ নথি না বদলালে reviewer প্রশ্ন করবেন: “README-র উদাহরণ কি এখনো চলবে?”

  • API documentation: সম্ভব হলে কোড থেকে তৈরি হোক — docstring বা JSDoc থেকে reference, আর HTTP API-র জন্য OpenAPI-এর মতো একটি machine-readable বিবরণ (REST API নকশা System Design কোর্সের REST API design পর্বে)। হাতে লেখা reference দ্রুত পুরোনো হয়।
  • Architecture নথি: একটি ছোট overview (C4-এর context আর container ছবি) আর ADR-এর সারি — পর্ব ৩৮।
  • Onboarding নথি: নতুন সদস্যের প্রথম সপ্তাহের পথ — কোন access লাগবে, কীভাবে local-এ চালাবেন, কোন ছোট issue দিয়ে শুরু, কাকে কী জিজ্ঞেস করবেন। নিয়ম: প্রতিটি নতুন সদস্য onboarding শেষে যে ধাপে আটকেছিলেন, সেটি ঠিক করে একটি PR দেবেন।
  • নথি সতেজ রাখা: পুরোনো নথি — documentation rot — অনেক সময় নথি না থাকার চেয়েও খারাপ, কারণ ভুল পথ দেখায়। প্রতিকার: CI-তে README-র command চালানো বা doctest, প্রতিটি পাতায় মালিক আর “শেষ যাচাই” তারিখ, CODEOWNERS দিয়ে docs-এর reviewer, আর যে নথি কেউ রাখবেন না তা মুছে ফেলা।

নিচের খেলনা checker একটি README-র শিরোনাম আর প্রথম লাইন দেখে ছয়টি মৌলিক অংশ — title, description, install, usage, contributing, license — আছে কি না বলে। এটি শুধু heading-এর নাম মেলায়, লেখার মান বিচার করে না:

// README completeness checker: reads only Markdown headings and the top lines.
const SECTIONS = {
  install:      /^#{2,3}\s*(install|installation|setup|getting started)\b/im,
  usage:        /^#{2,3}\s*(usage|how to use|examples?)\b/im,
  contributing: /^#{2,3}\s*contribut/im,
  license:      /^#{2,3}\s*licen[cs]e\b/im,
};
function check(name, text) {
  const lines = text.trim().split("\n");
  const missing = [];
  if (!/^#\s+\S/.test(lines[0])) missing.push("title");
  const desc = lines.slice(1).find((l) => l.trim() !== "");
  if (!desc || desc.startsWith("#")) missing.push("description");
  for (const [key, re] of Object.entries(SECTIONS)) if (!re.test(text)) missing.push(key);
  const note = missing.length ? `  missing: ${missing.join(", ")}` : "  complete";
  console.log(`${name.padEnd(13)} ${6 - missing.length}/6${note}`);
}
check("bazar-cart", `# bazar-cart
Shopping-cart library for a fictional online bazar app.
## Installation
npm install bazar-cart
## Usage
cart.add("rice-5kg", 2)
## Contributing
Read CONTRIBUTING.md before opening a pull request.
## License
MIT - see LICENSE`);
check("result-portal", `# result-portal
## Setup
pip install -r requirements.txt
## License
GPL-3.0-or-later`);
check("scripts", `Some helper scripts.
## Examples
python run.py --dry-run`);

আউটপুট:

bazar-cart    6/6  complete
result-portal 3/6  missing: description, usage, contributing
scripts       1/6  missing: title, description, install, contributing, license

bazar-cart-এ ছয়টিই আছে। result-portal-এ শিরোনামের পরের প্রথম লাইনটিই ## Setup — অর্থাৎ project কী করে তার কোনো বাক্য নেই, তাই description নেই; Setup শব্দটি install-এর সমার্থক হিসেবে ধরা হয়েছে, আর Licence/License দুই বানানই চলে (licen[cs]e). scripts-এ প্রথম লাইন # দিয়ে শুরু নয়, তাই title নেই; আর checker সবসময় প্রথম লাইনের পরের প্রথম অ-খালি লাইনটিকে description হিসেবে খোঁজে — এখানে সেটি ## Examples, একটি heading, তাই description-ও নেই (প্রথম লাইনের বাক্যটি গোনা হয় না); শুধু Examples usage হিসেবে গোনা হলো। সীমা: “## Usage” লিখে নিচে কিছু না রাখলেও এটি পাস করবে। এমন checker CI-তে একটি ন্যূনতম দরজা মাত্র; মান যাচাই করবেন মানুষ, review-এ।

৫ · জ্ঞান ভাগাভাগি আর bus factor — হিসাব করে দেখা

পর্ব ৪৪-এ code review-এর একটি উদ্দেশ্য হিসেবে bus factor দেখেছেন: কতজন মানুষ হঠাৎ না থাকলে project আটকে যাবে। একে truck factor-ও বলে। প্রশ্ন হলো, এটি কি অনুমান না হিসাব? Git-এর history থেকে একটি আনুমানিক হিসাব করা যায়।

পাড়ার মুদি দোকানের হিসাবের খাতা শুধু মালিক বোঝেন — কোন খদ্দেরের কত বাকি, কোন সাংকেতিক চিহ্নের কী মানে। মালিক এক সপ্তাহ অসুস্থ থাকলে দোকান চলে, কিন্তু বাকির হিসাব থেমে যায়। এখানে bus factor ১। ছেলে যদি খাতাটি পড়তে শেখে, bus factor ২।

প্রথম ধাপ: কে কোন ফাইলে কাজ করেছেন। একটি scratch repository-তে কাল্পনিক অনলাইন বাজার অ্যাপের ১০০টি commit বানিয়ে Git ২.৫৩-এ চালানো হয়েছে (চারজন কাল্পনিক লেখক):

$ git shortlog -sne HEAD
    46	Rahim <rahim@example.com>
    21	Nila <nila@example.com>
    18	Karim <karim@example.com>
    15	Sumi <sumi@example.com>
$ git shortlog -sn HEAD -- api/payments.py
     9	Rahim
     6	Karim

-s শুধু সংখ্যা দেখায়, -n বেশি থেকে কম সাজায়, -e email দেখায়; -- path একটি ফাইলে সীমিত করে। HEAD লেখা হয়েছে কারণ script বা pipe থেকে চালালে revision না দিলে git shortlog standard input থেকে log পড়ার অপেক্ষা করে। একই মানুষ দুই email-এ commit করলে আগে .mailmap দিয়ে মেলাতে হবে (পর্ব ৯), নইলে হিসাব ভুল আসবে। প্রতিটি ফাইলে এভাবে গুনলে নিচের টেবিল পাওয়া যায় — সেটিই আমাদের ইনপুট।

সরলীকৃত পদ্ধতি

Avelino, Passos, Hora ও Valente (ICPC ২০১৬, “A novel approach for estimating truck factors”)-এর ধারণা অনুসরণ করে, তবে অনেক সরল করে: (১) কোনো লেখক একটি ফাইল “জানেন” যদি সেই ফাইলের অন্তত ২৫% commit তাঁর। (মূল গবেষণায় এর বদলে degree of authorship নামের একটি ওজনযুক্ত মাপ আছে, যেখানে প্রথম লেখক হওয়া আর অন্যদের পরিবর্তনও হিসাবে আসে।) (২) যিনি সবচেয়ে বেশি ফাইল জানেন, তাঁকে সরান; সমান হলে বর্ণানুক্রমে প্রথমজন। (৩) যে ফাইলের জানা লেখক আর কেউ নেই, সেটি “অভিভাবকহীন”। (৪) অর্ধেকের বেশি ফাইল অভিভাবকহীন হলে থামুন — যতজন সরালেন, সেটিই truck factor.

# Truck-factor estimate, simplified (after the idea in Avelino et al. 2016).
# commits[file] = {author: commits to that file} -- fictional shop project
commits = {
    "api/orders.py":   {"Rahim": 14, "Sumi": 2},
    "api/payments.py": {"Rahim": 9, "Karim": 6},
    "api/users.py":    {"Sumi": 7, "Rahim": 1},
    "core/cart.py":    {"Rahim": 11, "Nila": 1},
    "core/stock.py":   {"Karim": 8},
    "core/price.py":   {"Rahim": 5, "Karim": 4},
    "web/app.js":      {"Nila": 12, "Sumi": 3},
    "web/cart.js":     {"Nila": 6},
    "docs/README.md":  {"Sumi": 3, "Rahim": 2, "Nila": 2},
    "ci/build.yml":    {"Rahim": 4},
}
SHARE = 0.25   # an author "knows" a file if they made >= 25% of its commits
owners = {f: {a for a, c in m.items() if c / sum(m.values()) >= SHARE}
          for f, m in commits.items()}
for f, o in owners.items():
    print(f"{f:16} knows: {', '.join(sorted(o))}")
removed, n = [], len(owners)
while True:
    left = {f: o - set(removed) for f, o in owners.items()}
    orphans = [f for f, o in left.items() if not o]
    print(f"removed={removed} -> orphan files {len(orphans)}/{n}")
    if len(orphans) > n / 2:          # more than half the files lost
        break
    count = {}
    for o in left.values():
        for a in o:
            count[a] = count.get(a, 0) + 1
    top = max(sorted(count), key=count.get)   # ties: alphabetical first
    removed.append(top)
print("truck factor =", len(removed))

আউটপুট:

api/orders.py    knows: Rahim
api/payments.py  knows: Karim, Rahim
api/users.py     knows: Sumi
core/cart.py     knows: Rahim
core/stock.py    knows: Karim
core/price.py    knows: Karim, Rahim
web/app.js       knows: Nila
web/cart.js      knows: Nila
docs/README.md   knows: Nila, Rahim, Sumi
ci/build.yml     knows: Rahim
removed=[] -> orphan files 0/10
removed=['Rahim'] -> orphan files 3/10
removed=['Rahim', 'Karim'] -> orphan files 6/10
truck factor = 2

প্রথম দশ লাইন হলো ২৫% নিয়মে মালিকানা। যেমন api/payments.py: Rahim 9/15 = 60%, Karim 6/15 = 40% — দুজনেই জানেন। core/cart.py-এ Nila-র ১/১২ ≈ ৮% — নিয়মের নিচে, তাই শুধু Rahim. তারপর greedy ধাপ: Rahim ৬টি ফাইল জানেন, তাঁকে সরালে ৩টি ফাইল (orders.py, cart.py, build.yml) অভিভাবকহীন — ৩ > ৫ নয়, তাই চালিয়ে যাওয়া। এখন Karim আর Nila দুজনেই ৩টি করে জানেন; বর্ণানুক্রমে Karim সরলেন, আর payments.py, stock.py, price.py যোগ হয়ে ৬/১০ — অর্ধেকের বেশি। ফল: truck factor = ২. দশটি ফাইল, চারজন মানুষ, অথচ মাত্র দুজন চলে গেলেই project-এর বেশিরভাগ অংশ কেউ জানেন না।

কে এখনো কতটি ফাইল জানেন (মোট ১০টি ফাইল)
সরানো হয়েছে
Rahim
Karim
Nila
Sumi
অভিভাবকহীন ফাইল
Truck factor
  1. মালিকানা গোনা। ২৫% নিয়মে Rahim ৬টি ফাইল জানেন (orders, payments, cart, price, README, build), Karim ৩টি (payments, stock, price), Nila ৩টি (app.js, cart.js, README), Sumi ২টি (users, README). কোনো ফাইল এখনো অভিভাবকহীন নয়।
  2. সবচেয়ে বেশি জানা মানুষ সরানো। Rahim সরলেন। যে তিনটি ফাইলে শুধু তিনি ছিলেন — orders, cart, build — অভিভাবকহীন হলো: ৩/১০.
  3. থামার শর্ত যাচাই। ৩টি কি ১০-এর অর্ধেকের বেশি? না (৫-এর বেশি লাগবে)। এখন Karim আর Nila সমান ৩টি করে; বর্ণানুক্রমে Karim আগে, তাই তিনিই পরের জন।
  4. Karim সরানো। payments আর price-এ Rahim আগেই নেই, stock-এ শুধু Karim — তিনটিই অভিভাবকহীন। মোট ৬/১০.
  5. থামুন। ৬ > ৫, তাই হিসাব শেষ। দুজন সরানো হয়েছে: truck factor ২. Nila আর Sumi থাকলেও web অংশ আর README ছাড়া বাকিটা কেউ জানেন না।
  6. Tie উল্টে দেখা। ধাপ ৩-এ Karim-এর বদলে Nila সরালে app.js আর cart.js অভিভাবকহীন হয় — ৫/১০, ঠিক অর্ধেক, অর্ধেকের বেশি নয়; আরও একজন সরাতে হয়, ফল ৩. Greedy পদ্ধতি একটি আনুমানিক হিসাব, নিখুঁত উত্তর নয়; tie-এর নিয়ম, ২৫%-এর সীমা আর ফাইলের ওজন — সব ফল বদলায়। সংখ্যাটি একটি সতর্কসংকেত, রায় নয়।

Bus factor বাড়াবেন কীভাবে

  • Review-এর বণ্টন: একই মানুষ সব review না করে, অন্য অংশের মানুষকেও reviewer করা; CODEOWNERS-এ একটি অংশে অন্তত দুজন।
  • জুটি বেঁধে কাজ: pair programming আর mob programming (পর্ব ৪৪) দ্রুত জ্ঞান ছড়ায় — বিশেষ করে knowledge silo ভাঙতে।
  • কাজের ঘূর্ণন: on-call, release আর “এই সপ্তাহে payments-এর bug” পালা করে।
  • ভেতরের আলোচনা: মাসে একবার ২০ মিনিটের internal talk বা brown-bag session, রেকর্ড আর নোটসহ।
  • নথি: অংশ ৪-এর explanation নথি আর ADR — মানুষ চলে গেলেও “কেন” থেকে যায়।

Truck factor কম হওয়া একটি project risk; risk register-এ কীভাবে লিখবেন তা পর্ব ৬২-এ (Risk আর quality management).

৬ · Open source — সংজ্ঞা, অবদানের পথ আর governance

Open source মানে শুধু “কোড দেখা যায়” নয়। Open Source Initiative (OSI) ১৯৯৮ সালে প্রতিষ্ঠিত হয়, আর তাদের Open Source Definition-এ দশটি শর্ত আছে — Debian Free Software Guidelines থেকে নেওয়া — যেমন অবাধে আবার বিতরণ, source code পাওয়া, পরিবর্তিত কাজ বানানোর অনুমতি, কোনো ব্যক্তি বা কাজের ক্ষেত্রের বিরুদ্ধে বৈষম্য না করা। OSI যে license-গুলো এই শর্ত মানে বলে পরীক্ষা করেছে, সেগুলোকে “OSI-approved” বলে। “কোড GitHub-এ আছে কিন্তু license নেই” — এমন কোড আইনগতভাবে সাধারণত ব্যবহারের অনুমতি দেয় না, কারণ কপিরাইট নিজে থেকেই লেখকের।

Free software বনাম open source: Richard Stallman ১৯৮৩ সালে GNU project ঘোষণা করেন আর ১৯৮৫ সালে Free Software Foundation (FSF) গড়েন। FSF-এর free software-এর সংজ্ঞা চারটি স্বাধীনতা: চালানো, পড়ে বদলানো, কপি বিতরণ আর পরিবর্তিত কপি বিতরণ — “free” মানে স্বাধীনতা, দাম নয়। ১৯৯৮ সালে কয়েকজন “open source” শব্দটি বেছে নেন, ব্যবসায়ীদের কাছে ব্যবহারিক সুবিধার ভাষায় বলার জন্য। দুই সংজ্ঞায় অনুমোদিত license-এর তালিকা প্রায় মেলে, কিন্তু দৃষ্টিভঙ্গি আলাদা: FSF একে ব্যবহারকারীর স্বাধীনতার নৈতিক প্রশ্ন হিসেবে দেখে, OSI উন্নয়ন-পদ্ধতির উপযোগিতা হিসেবে। দুই পক্ষের অবস্থান তাদের নিজেদের লেখায় পড়ে নিজে বিচার করুন; অনেকে নিরপেক্ষ শব্দ “FOSS” বা “FLOSS” ব্যবহার করেন।

একটি অবদান — issue থেকে merge পর্যন্ত

পর্ব ১৬-এ (Pull request আর fork) fork-এর যন্ত্রপাতি আর review-এর নিয়ম দেখেছেন। এখানে পুরো যাত্রা, একটি কাল্পনিক open-source library bazar-cart-এ প্রথম অবদান:

অবদানের খাতা
ধাপ
কোথায়
Command বা কাজ
  1. Issue খোঁজা। Maintainer-রা নতুনদের জন্য সহজ কাজে good first issue লেবেল দেন। Issue #42: “README-র install command-এ package-এর নাম ভুল।” ছোট, স্পষ্ট, ঝুঁকি কম — প্রথম অবদানের জন্য আদর্শ।
  2. নিয়ম পড়া আর জানানো। CONTRIBUTING.md বলছে DCO sign-off লাগবে, commit Conventional Commits ধাঁচে; CODE_OF_CONDUCT আর LICENSE (MIT) দেখা হলো। Issue-এ মন্তব্য: “আমি এটি নিতে চাই” — যাতে দুজন একই কাজ না করেন। বড় পরিবর্তন হলে আগে issue-এ প্রস্তাব আলোচনা করুন।
  3. Fork আর clone. Platform-এ fork, তারপর নিজের fork clone করে মূল repository-কে upstream নামে যোগ করা (পর্ব ১৪ আর ১৬): origin = আপনার fork, upstream = মূল project.
  4. আলাদা branch. main-এ সরাসরি নয় — কাজের নামে একটি branch, যাতে পরে upstream-এর সাথে মেলানো সহজ হয়।
  5. পরিবর্তন আর test. README ঠিক করা হলো, আর CONTRIBUTING-এ বলা test ও lint চালানো হলো। নথির পরিবর্তনেও এটি জরুরি — অনেক project README-র উদাহরণও test করে।
  6. Sign-off দিয়ে commit. -s বার্তার শেষে Signed-off-by: নাম <email> trailer যোগ করে — DCO-তে সম্মতি (পর্ব ১৮)। এটি cryptographic স্বাক্ষর নয়।
  7. Push আর PR. নিজের fork-এ push, তারপর মূল repository-তে PR. বিবরণে template পূরণ আর Fixes #42 — একটি closing keyword, merge হলে issue নিজে বন্ধ হবে।
  8. CI আর review. CI-তে DCO check আর test সবুজ। Maintainer অনুরোধ করলেন Windows-এর command-ও যোগ করতে। আপনি fixup commit দিয়ে push করলেন আর ধন্যবাদ জানালেন — volunteer maintainer-এর সময় সীমিত, তাই ধৈর্য রাখুন; এক সপ্তাহ সাড়া না এলে ভদ্রভাবে একবার মনে করিয়ে দিন।
  9. Merge. Maintainer squash merge করলেন, #42 বন্ধ হলো, পরের release-এর changelog-এ আপনার নাম। এরপর নিজের fork হালনাগাদ: git fetch upstream, তারপর নিজের main-এ upstream/main fast-forward. পুরোনো branch মুছে ফেলুন।

CLA বনাম DCO

Project জানতে চায় আপনার অবদান ব্যবহারের অধিকার তাদের আছে। দুই প্রধান পথ:

✍️ CLA

Contributor License Agreement — একটি আলাদা আইনি চুক্তি, প্রায়ই একবার অনলাইনে স্বাক্ষর। আপনি project-এর মালিক প্রতিষ্ঠানকে বিস্তৃত license দেন (কিছু CLA-তে কপিরাইটই হস্তান্তর)। এতে প্রতিষ্ঠান পরে license বদলাতেও পারে — যা অনেক অবদানকারী অপছন্দ করেন।

🖊️ DCO

Developer Certificate of Origin — ২০০৪ সালে Linux kernel-এ চালু হওয়া ছোট ঘোষণা: “এই কোড জমা দেওয়ার অধিকার আমার আছে, project-এর license-এ।” প্রতিটি commit-এ Signed-off-by; আলাদা চুক্তি নেই, কপিরাইট আপনারই থাকে।

Governance, maintainer আর code of conduct

কে সিদ্ধান্ত নেন? ছোট project-এ একজন maintainer; কিছু বড় project-এ একজন চূড়ান্ত সিদ্ধান্তদাতা — রসিকতা করে বলা হয় BDFL (“benevolent dictator for life”) — যেমন Python দীর্ঘদিন Guido van Rossum-এর এই ভূমিকায় চলেছে, ২০১৮ সালে তিনি সরে দাঁড়ানোর পরে নির্বাচিত steering council এসেছে। অন্য governance model: meritocratic committer (যেমন Apache Software Foundation-এর project-এ), নির্বাচিত কমিটি, বা একটি কোম্পানি-নেতৃত্বাধীন project. ভালো project এটি GOVERNANCE.md-এ লিখে রাখে — কীভাবে কেউ maintainer হন, সিদ্ধান্ত কীভাবে, মতবিরোধে কী হয়।

Code of conduct লেখে কোন আচরণ গ্রহণযোগ্য, কোথায় অভিযোগ করবেন আর কে কীভাবে ব্যবস্থা নেবেন। বহুল ব্যবহৃত একটি নমুনা হলো Contributor Covenant, ২০১৪ সালে Coraline Ada Ehmke-এর শুরু করা; সংস্করণ সময়ের সাথে বদলেছে, তাই ব্যবহারের আগে তাদের সাইটে সর্বশেষটি দেখে নিন। অভিযোগের ঠিকানা আর ব্যবস্থা নেওয়ার মানুষ না থাকলে নথিটি কেবল সাজসজ্জা।

বাংলাদেশে: দেশে বিভিন্ন open-source আর developer community আছে — বিশ্ববিদ্যালয়ের programming club, শহরভিত্তিক meetup, অনলাইন গ্রুপ; কিছু community software-কে বাংলায় অনুবাদ (localization) আর বাংলা ভাষার tool নিয়ে কাজ করে। সক্রিয় কোনটি, তা সময়ের সাথে বদলায় — নিজের এলাকা বা বিশ্ববিদ্যালয়ে খোঁজ নিন। অনুবাদ, নথি ঠিক করা আর bug-এর বিস্তারিত রিপোর্টও পূর্ণ মর্যাদার অবদান।

৭ · Software license — permissive থেকে network copyleft

একটি software license হলো কপিরাইটের মালিকের দেওয়া অনুমতি আর তার শর্ত। মূল প্রশ্ন একটাই: আপনি যদি এই কোড ব্যবহার করে কিছু বানিয়ে অন্যকে দেন, তাহলে আপনার নিজের কোডের ওপর কী শর্ত পড়বে? উত্তরের মাত্রা ধরে license-গুলোকে একটি বর্ণালিতে সাজানো যায়:

License-এর বর্ণালি — শর্ত কতদূর ছড়ায়

Permissive → weak copyleft → strong copyleft → network copyleft

License-এর বর্ণালি: permissive, weak copyleft, strong copyleft, network copyleft কম শর্ত বেশি শর্ত ১ · Permissive ২ · Weak copyleft ৩ · Strong copyleft ৪ · Network copyleft MIT · BSD-2/3-Clause Apache-2.0 + patent শর্ত: notice আর license-এর লেখা রাখা MPL-2.0 — ফাইল ধরে LGPL — library ধরে বদলানো ফাইল বা library-র source খোলা GPL-2.0 · GPL-3.0 বিতরণ করা পুরো মিলিত কাজ একই license-এ, source-সহ AGPL-3.0 network-এ সেবা দিলেও ব্যবহারকারীকে source দিতে হয় বর্ণালির বাইরে বাঁয়ে: CC0 (public domain-ধাঁচ)
ছবি ৬৩.২ — ডানে গেলে license-এর শর্ত আপনার কোডের আরও বড় অংশে পৌঁছায়। প্রতিটি license-এর সঠিক শর্ত তার পূর্ণ লেখায়; এটি শুধু মোটা দাগের মানচিত্র।
Licenseমূল শর্তবিশেষ দিক
MITকপিরাইট notice আর license-এর লেখা রাখাখুব ছোট; patent নিয়ে স্পষ্ট কিছু বলে না
BSD-2-Clause / BSD-3-ClauseMIT-এর মতো৩-clause সংস্করণে মালিকের নাম প্রচারে ব্যবহার নিষেধ
Apache-2.0 (২০০৪)notice, পরিবর্তিত ফাইলে চিহ্ন, NOTICE ফাইল থাকলে তা রাখাঅবদানকারীদের স্পষ্ট patent grant; patent মামলা করলে সেই অনুমতি বাতিল
MPL-2.0 (২০১২)MPL ফাইল বদলালে সেই ফাইলের source খোলা রাখাফাইল-পর্যায়ের weak copyleft; বাকি ফাইল যেকোনো license-এ
LGPL-2.1 / LGPL-3.0library বদলালে তার source; ব্যবহারকারী যেন library বদলে আবার জুড়তে পারেনlibrary ব্যবহারকারী প্রোগ্রাম নিজে ভিন্ন license-এ থাকতে পারে, শর্তসাপেক্ষে
GPL-2.0 (১৯৯১) / GPL-3.0 (২০০৭)বিতরণ করা মিলিত কাজ (derivative work) GPL-এ, source-সহstrong copyleft; GPL-3.0-এ patent আর “tivoization” নিয়ে নতুন ধারা
AGPL-3.0 (২০০৭)GPL-3.0-এর সব, আর ধারা ১৩network copyleft: বদলানো প্রোগ্রাম network-এ ব্যবহারকারীকে সেবা দিলে তাঁদের source দেওয়ার সুযোগ রাখতে হয়
CC0-1.0প্রায় কোনো শর্ত নেইযতদূর আইন দেয়, অধিকার ছেড়ে দেওয়া (public domain), না পারলে সবচেয়ে উদার license; এটি স্পষ্ট বলে যে patent-এর অধিকার এতে ছাড়া হয় না, তাই code-এর জন্য অনেকে অন্য পথ নেন

Permissive license বলে “যা খুশি করুন, শুধু নাম রাখুন”; copyleft বলে “বিতরণ করলে একই স্বাধীনতা পরের মানুষকেও দিন”। GPL-এর একটি সূক্ষ্ম কথা: শর্ত জাগে বিতরণে। শুধু নিজের server-এ বদলানো GPL প্রোগ্রাম চালিয়ে সেবা দিলে সাধারণত বিতরণ হয় না — এই ফাঁকটি বন্ধ করতেই AGPL-এর ধারা ১৩.

আইনি পরামর্শ নয়। License-এর ব্যাখ্যা দেশের আইন, চুক্তির ভাষা আর ঘটনার খুঁটিনাটির ওপর নির্ভর করে; কয়েকটি প্রশ্নে বিশেষজ্ঞরাও একমত নন (যেমন dynamic linking কখন “মিলিত কাজ”)। এখানের নিয়মগুলো প্রচলিত ব্যাখ্যা, প্রধানত FSF আর license-লেখকদের প্রকাশিত মত। বাণিজ্যিক বা ঝুঁকিপূর্ণ সিদ্ধান্তে প্রতিষ্ঠানের আইনি দল বা যোগ্য আইনজীবীর পরামর্শ নিন। License-এর নৈতিক দিক — যেমন AI-এর তৈরি কোডে কার দায় — পর্ব ৬৪-এ (পেশাগত নৈতিকতা)।

License compatibility — কোন দিকে মেলানো যায়

License compatibility প্রশ্ন: license A-র কোড আমার project-এ নিয়ে পুরোটা license B-তে বিতরণ করা যাবে কি না? উত্তর দিক-নির্ভর। MIT-এর কোড GPL-3.0 project-এ নেওয়া যায় (MIT-এর notice রেখে), কিন্তু উল্টোটা নয় — GPL কোড নিলে পুরো বিতরণ করা কাজটিকে GPL-এর শর্ত মানতে হয়। FSF-এর মতে Apache-2.0 GPL-3.0-এর সাথে মেলে, কিন্তু GPL-2.0-এর সাথে নয় (Apache-2.0-এর patent-বাতিল আর indemnification-এর মতো কিছু শর্ত GPL-2.0 অনুমতি দেয় না); আর “GPL-2.0-only” কোড GPL-3.0-এ যায় না, যতক্ষণ না লেখক “or later” অনুমতি দেন। নিচের খেলনা টেবিল এই প্রচলিত ব্যাখ্যাগুলো ধরে:

// EDUCATIONAL TOY - NOT LEGAL ADVICE. A simplified table of common readings
// (mostly the FSF's). Question: may code under license A go INTO a project
// that is distributed under license B?
const B = ["MIT", "Apache-2.0", "MPL-2.0", "LGPL-2.1-only",
           "GPL-2.0-only", "GPL-3.0-only", "AGPL-3.0-only"];
// row = A (code you bring in); one letter per column of B:
// Y = yes, N = no, C = yes, but A's copyleft keeps applying to A's part
const M = {
  "MIT":           "YYYYYYY",
  "Apache-2.0":    "YYYNNYY",
  "MPL-2.0":       "CCYYYYY",
  "LGPL-2.1-only": "CCCYYYY",
  "GPL-2.0-only":  "NNNNYNN",
  "GPL-3.0-only":  "NNNNNYY",
  "AGPL-3.0-only": "NNNNNCY",
};
const WHY = { Y: "yes (keep copyright and license text)",
              N: "NO  (needs relicensing or permission)",
              C: "yes, with conditions on A's part" };
function check(a, b) {
  if (!(a in M) || !B.includes(b)) return "unknown - ask a person who knows";
  return WHY[M[a][B.indexOf(b)]];
}
const asks = [["MIT", "GPL-3.0-only"], ["Apache-2.0", "GPL-3.0-only"],
  ["Apache-2.0", "GPL-2.0-only"], ["GPL-3.0-only", "MIT"],
  ["MPL-2.0", "Apache-2.0"], ["GPL-2.0-only", "GPL-3.0-only"],
  ["AGPL-3.0-only", "GPL-3.0-only"], ["BSD-3-Clause", "MIT"]];
for (const [a, b] of asks)
  console.log(`${a.padEnd(13)} into ${b.padEnd(13)}: ${check(a, b)}`);

আউটপুট:

MIT           into GPL-3.0-only : yes (keep copyright and license text)
Apache-2.0    into GPL-3.0-only : yes (keep copyright and license text)
Apache-2.0    into GPL-2.0-only : NO  (needs relicensing or permission)
GPL-3.0-only  into MIT          : NO  (needs relicensing or permission)
MPL-2.0       into Apache-2.0   : yes, with conditions on A's part
GPL-2.0-only  into GPL-3.0-only : NO  (needs relicensing or permission)
AGPL-3.0-only into GPL-3.0-only : yes, with conditions on A's part
BSD-3-Clause  into MIT          : unknown - ask a person who knows

প্রতিটি সারি একটি license A, প্রতিটি অক্ষর একটি project-license B — যেমন Apache-2.0-এর সারি YYYNNYY-এর পঞ্চম অক্ষর N মানে GPL-2.0-only project-এ নেওয়া যায় না। GPL-3.0-only into MIT NO — পুরোটা MIT-এ বিতরণ করা যাবে না। MPL-2.0 into Apache-2.0 শর্তসহ হ্যাঁ: MPL ফাইলগুলো MPL-ই থাকে আর তাদের source খোলা রাখতে হয়। AGPL-3.0-only into GPL-3.0-only-ও শর্তসহ: GPL-3.0 আর AGPL-3.0-এর ধারা ১৩ দুটি মেলাতে দেয়, কিন্তু মিলিত কাজে AGPL অংশের network শর্ত থেকে যায়। শেষ লাইনটি জরুরি: BSD-3-Clause টেবিলে নেই, তাই checker অনুমান না করে “unknown” বলে — বাস্তবে BSD-3-Clause উদার, কিন্তু যন্ত্রের নিয়ম হওয়া উচিত “না জানলে মানুষকে জিজ্ঞেস”। সীমা: এখানে library হিসেবে আলাদা জোড়া বনাম কোড কপি, “or later” বনাম “only”, exception, আর আলাদা প্রোগ্রাম হিসেবে পাশাপাশি বিতরণ (aggregate) — কিছুই ধরা হয়নি। এটি শেখার জন্য; আইনি সিদ্ধান্তে নয়।

NOTICE ফাইল আর attribution

Apache-2.0-এর ধারা ৪ বলে: মূল project-এ NOTICE ফাইল থাকলে আপনার বিতরণেও তার attribution রাখতে হবে। বাস্তবে একটি app-এর “About → Open source licenses” পাতা বা THIRD_PARTY_NOTICES ফাইল এই কাজই করে: প্রতিটি dependency-র নাম, version, license আর কপিরাইট লাইন। Permissive license-এরও এটাই প্রায় একমাত্র শর্ত — আর এটাই সবচেয়ে বেশি ভুলে যাওয়া হয়।

৮ · SPDX, license scan আর একটি license বেছে নেওয়া

“MIT”, “The MIT License”, “Expat”, “X11-style” — মানুষ একই license-কে নানা নামে লেখে, যন্ত্র বিভ্রান্ত হয়। SPDX (Software Package Data Exchange, Linux Foundation-এর project, ২০২১ সালে ISO/IEC 5962 হিসেবে মান) প্রতিটি license-কে একটি নির্দিষ্ট ছোট নাম দেয় — SPDX license identifier: MIT, Apache-2.0, GPL-2.0-only, GPL-3.0-or-later. ২০১৭ সালের শেষে SPDX license list-এর সংস্করণ ৩.০ থেকে GPL পরিবারের জন্য “-only” আর “-or-later” আলাদা নাম এসেছে; পুরোনো GPL-3.0 এখন deprecated, কারণ এটি থেকে বোঝা যেত না কোনটি। প্রতিটি source ফাইলের শুরুতে এক লাইন:

// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 The bazar-cart contributors

একাধিক license একসাথে লিখতে আছে SPDX expression: OR = বেছে নেওয়ার স্বাধীনতা (dual licensing, যেমন Rust-এর জগতে প্রচলিত MIT OR Apache-2.0), AND = দুটিই একসাথে মানতে হবে, আর WITH = একটি license-এর সাথে একটি license exception — যেমন OpenJDK-র GPL-2.0-only WITH Classpath-exception-2.0, যা library ব্যবহারকারী প্রোগ্রামকে GPL-এর শর্ত থেকে ছাড় দেয়। অগ্রাধিকার: WITH সবচেয়ে শক্ত, তারপর AND, তারপর OR; বন্ধনী দিয়ে বদলানো যায়। নিচের ছোট parser এটি গাছ হিসেবে দেখায়:

import re
# Tiny SPDX license-expression parser. Precedence: WITH > AND > OR; ( ) groups.
def parse(text):
    t = re.findall(r"\(|\)|[A-Za-z0-9.+:-]+", text)
    pos = 0
    def peek(): return t[pos] if pos < len(t) else None
    def take():
        nonlocal pos; pos += 1; return t[pos - 1]
    def chain(op, sub):                  # left-to-right chain of one operator
        node = sub()
        while peek() == op:
            take(); node = (op, node, sub())
        return node
    def atom():
        if peek() == "(":
            take(); node = or_expr()
            if take() != ")": raise ValueError("missing )")
            return node
        lic = take()
        if peek() == "WITH":
            take(); return ("WITH", lic, take())
        return lic
    def and_expr(): return chain("AND", atom)
    def or_expr():  return chain("OR", and_expr)
    tree = or_expr()
    if pos != len(t): raise ValueError("unexpected " + t[pos])
    return tree
def show(n, d=1):
    pad = "  " * d
    if isinstance(n, str): print(pad + "license:", n)
    elif n[0] == "WITH": print(pad + "license:", n[1], "+ exception:", n[2])
    else: print(pad + n[0]); show(n[1], d + 1); show(n[2], d + 1)
for e in ["MIT OR Apache-2.0", "GPL-2.0-only WITH Classpath-exception-2.0",
          "MIT AND Apache-2.0 OR BSD-3-Clause", "MIT AND (Apache-2.0 OR BSD-3-Clause)"]:
    print(e); show(parse(e))

আউটপুট:

MIT OR Apache-2.0
  OR
    license: MIT
    license: Apache-2.0
GPL-2.0-only WITH Classpath-exception-2.0
  license: GPL-2.0-only + exception: Classpath-exception-2.0
MIT AND Apache-2.0 OR BSD-3-Clause
  OR
    AND
      license: MIT
      license: Apache-2.0
    license: BSD-3-Clause
MIT AND (Apache-2.0 OR BSD-3-Clause)
  AND
    license: MIT
    OR
      license: Apache-2.0
      license: BSD-3-Clause

এটি একটি recursive-descent parser: or_expr ডাকে and_expr-কে, সেটি ডাকে atom-কে — নিচের function যত গভীরে, তার operator তত শক্ত করে বাঁধে। তাই তৃতীয় উদাহরণ MIT AND Apache-2.0 OR BSD-3-Clause পড়া হলো “(MIT AND Apache-2.0) OR BSD-3-Clause” — অর্থাৎ হয় দুটি একসাথে মানুন, নয়তো শুধু BSD. চতুর্থটিতে বন্ধনী অর্থ পুরো বদলে দিল: MIT সবসময়, আর তার সাথে Apache বা BSD-এর একটি। একই চারটি শব্দ, দুই রকম আইনি অর্থ — এজন্যই বন্ধনী বাদ দিয়ে লেখা বিপজ্জনক। WITH আলাদা node নয়, একটি license-এর সাথে জোড়া থাকে। সীমা: আসল SPDX-এ নামগুলো অফিসিয়াল তালিকার সাথে মেলানো, LicenseRef- নামের নিজস্ব license আর ভুল লেখায় স্পষ্ট বার্তা দেওয়া — এগুলো এখানে নেই।

Dependency-র license scan

আপনার app-এর ভেতরে শত শত dependency, আর তাদেরও dependency. হাতে দেখা অসম্ভব, তাই license scanning tool package-এর metadata আর ফাইলের লেখা পড়ে প্রতিটির license বের করে, তারপর দলের নীতির সাথে মেলায়: “permissive চলবে; LGPL হলে review; GPL/AGPL হলে আটকানো; license না পেলে আটকানো”। লেখার সময়ের পরিচিত কিছু উদাহরণ: ScanCode Toolkit আর FOSSology (ফাইল ধরে গভীর scan), npm-এর জন্য license-checker-ধাঁচের package, Python-এর জন্য pip-licenses, আর hosting platform-এর dependency review — সুবিধা tool আর platform-ভেদে আলাদা। এটি CI-এর একটি ধাপ হিসেবে চালান (পর্ব ৫৮, Continuous integration), যাতে নতুন dependency যোগের PR-এই সমস্যা ধরা পড়ে। Package-এর নিজের license ঘোষণা করবেন metadata-তে: npm-এ package.json-এর "license" ঘরে SPDX expression (দেখুন npm আর tooling), Python-এ pyproject.toml-এ (দেখুন Packaging আর PyPI). Dependency-র তালিকা নিজেও software supply chain-এর অংশ (পর্ব ৫৭)।

একটি license বেছে নেওয়া — কাল্পনিক “হিসাবখাতা” library

ধরুন আপনি মুদি দোকানের বাকির হিসাব রাখার একটি ছোট open-source library বানিয়েছেন, নাম “হিসাবখাতা”। কোন license? নিচের ধাপগুলো একটি যুক্তির পথ, একমাত্র ঠিক উত্তর নয়:

সিদ্ধান্তের খাতা
প্রশ্ন
উত্তর
প্রার্থী
  1. লক্ষ্য আগে। আপনি চান যত বেশি দোকানের app — বাণিজ্যিকগুলোও — library-টি নিক। তাহলে শর্ত যত কম, গ্রহণ তত সহজ: permissive দিকে ঝোঁক। লক্ষ্য যদি হতো “উন্নতি সবার কাছে ফিরে আসুক”, পথ হতো copyleft.
  2. Dependency scan. চারটির মধ্যে একটি chart library GPL-3.0-only. সেটি সাথে নিয়ে বিতরণ করলে মিলিত কাজ GPL-এর শর্তে পড়ে — permissive লক্ষ্যের সাথে মেলে না। সমাধান: MIT license-এর বিকল্প library, অথবা chart অংশকে ঐচ্ছিক আলাদা package বানানো।
  3. Patent. কোম্পানির কর্মীরা অবদান রাখবেন। Apache-2.0-এর স্পষ্ট patent grant আর patent-মামলায় অনুমতি বাতিলের ধারা ব্যবহারকারীদের বাড়তি নিশ্চয়তা দেয়; MIT এ বিষয়ে চুপ।
  4. Copyleft বিবেচনা। MPL-2.0 (ফাইল-পর্যায়ে) মাঝামাঝি পথ হতে পারত; LGPL-এর relink শর্ত ছোট দোকান-app-এর জন্য জটিল; AGPL বড় সেবা-প্রদানকারীর জন্য — লক্ষ্য ১-এর সাথে কোনোটিই মানানসই নয়।
  5. ইকোসিস্টেমের রীতি। Library-টি Python-এ; সেখানে MIT আর Apache-2.0 দুটিই প্রচলিত, তাই কেউ অবাক হবেন না। (Rust-এ হলে MIT OR Apache-2.0 প্রচলিত রীতি।) সিদ্ধান্ত: Apache-2.0.
  6. কাগজপত্র। মূলে LICENSE-এ পূর্ণ লেখা, নিজের attribution-এর জন্য NOTICE, প্রতিটি ফাইলে SPDX-License-Identifier: Apache-2.0, README-র License অংশ, pyproject.toml-এ license, CI-তে dependency scan, আর CONTRIBUTING-এ DCO. সিদ্ধান্তটি একটি ছোট ADR-এ লিখে রাখুন — পরে কেউ জিজ্ঞেস করলে উত্তর থাকবে।

আরও গভীরে: SPDX শুধু license-এর নাম নয় — পুরো software bill of materials (SBOM) লেখার একটি format, যেখানে প্রতিটি package, version, hash আর license থাকে; CycloneDX আরেকটি প্রচলিত format. FSFE-র REUSE নির্দেশিকা প্রতিটি ফাইলে SPDX লাইন আর LICENSES/ ফোল্ডারে license-এর লেখা রাখার একটি যন্ত্রে-যাচাইযোগ্য নিয়ম দেয়। License-এর ইতিহাস আর দর্শনের জন্য Lawrence Rosen-এর Open Source Licensing (২০০৪) আর FSF-এর license-তালিকার মন্তব্য পড়ার মতো; Karl Fogel-এর Producing Open Source Software (প্রথম সংস্করণ ২০০৫, অনলাইনে বিনামূল্যে) governance আর দৈনন্দিন রক্ষণাবেক্ষণের ভালো পরিচিতি।

৯ · AI-এর যুগে দলগত কাজ, নথি আর license

AI এখন সভার নোটের সারাংশ লেখে, README-র খসড়া দেয়, আর কোড প্রস্তাব করে। এতে সময় বাঁচে — কিন্তু দলের কাজে তিনটি নতুন ঝুঁকি আসে: ভুল তথ্য আত্মবিশ্বাসের সাথে লেখা নথি, license-এর উৎস হারানো কোড, আর prompt-এ গোপন তথ্য।

AI প্রায়ই যা করেঝুঁকিযাচাই
License-এর শর্ত বা compatibility আত্মবিশ্বাসের সাথে “সরলভাবে” বলে, কখনো উল্টো দিকেGPL কোড permissive project-এ ঢোকেLicense-এর আসল লেখা, FSF/OSI-এর প্রকাশিত মত; সন্দেহে আইনি দল
অস্তিত্বহীন SPDX নাম বা পুরোনো সংস্করণ লেখেscan tool “unknown” দেখায়, বা ভুল license ঘোষণাSPDX license list-এ নাম মেলানো
প্রশিক্ষণের কোডের প্রায় হুবহু অংশ দেয়, উৎস ছাড়াঅন্যের কপিরাইট আর license শর্ত না মেনে ব্যবহারলম্বা অস্বাভাবিক নির্দিষ্ট কোডে উৎস খোঁজা; দলের AI-নীতি; tool-এর duplicate-filter
README-তে অস্তিত্বহীন command, flag বা config লেখেনতুন সদস্য প্রথম দিনেই আটকাননথির প্রতিটি command একটি throwaway clone-এ চালানো
সভার সারাংশে সিদ্ধান্ত “বানিয়ে” ফেলে বা দ্বিমত বাদ দেয়দল ভুল জিনিস মেনে নেয়সঞ্চালক সারাংশ পড়ে উপস্থিতদের দিয়ে মিলিয়ে নেন
Fork-sync বা history পরিষ্কারে reset --hard, push --force সতর্কতা ছাড়া দেয়অন্যের কাজ মুছে যায়git help, --force-with-lease, আগে scratch clone-এ

License-এর প্রশ্নে AI-কে একটি সহকারী হিসেবে ব্যবহার করুন — উত্তরদাতা নয়। Prompt-এ উৎস চাইতে আর অনিশ্চয়তা স্বীকার করতে বলুন:

আমার project-এর license Apache-2.0. আমি একটি dependency যোগ করতে চাই যার package metadata বলছে "LGPL-2.1-or-later". তুমি আইনজীবী নও, তাই: ১. এই দুটি একসাথে বিতরণে প্রচলিত ব্যাখ্যা কী — library আলাদাভাবে জোড়া আর কোড কপি করা, দুই ক্ষেত্রে আলাদা করে বলো। ২. প্রতিটি দাবির পাশে license-এর কোন ধারা বা কোন প্রকাশিত উৎস (FSF, license-লেখক) থেকে বলছ, তা লেখো। ৩. যেখানে বিশেষজ্ঞরা একমত নন বা তুমি নিশ্চিত নও, সেখানে স্পষ্ট করে "অনিশ্চিত" লেখো। ৪. আমাকে আইনি দলকে কোন ৩টি প্রশ্ন জিজ্ঞেস করা উচিত, তার তালিকা দাও।

AI ব্যবহারের আগে-পরে চেকলিস্ট

পরীক্ষা ও ইন্টারভিউতে: (১) Bus factor কী, কীভাবে বাড়াবেন? — কতজন চলে গেলে project আটকায়; review-এর বণ্টন, pairing, নথি, কাজের ঘূর্ণন। (২) Permissive আর copyleft-এর পার্থক্য? — permissive শুধু notice চায়; copyleft বিতরণে একই license আর source চায়। (৩) AGPL কেন এলো? — GPL-এর শর্ত বিতরণে জাগে; network সেবায় বিতরণ হয় না, ধারা ১৩ সেই ফাঁক বন্ধ করে। (৪) CLA আর DCO-র পার্থক্য? — CLA আলাদা আইনি চুক্তি, প্রায়ই বিস্তৃত অধিকার দেয়; DCO প্রতি commit-এ ছোট ঘোষণা, Signed-off-by দিয়ে। (৫) Asynchronous যোগাযোগ কখন ভালো? — অবস্থা, প্রস্তাব, review আর সিদ্ধান্তের রেকর্ডে; আবেগী দ্বিমত বা incident-এ synchronous.

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১Brooks বলেছিলেন দেরি হওয়া project-এ মানুষ যোগ করলে আরও দেরি হয়। তাহলে বড় software কীভাবে শত শত মানুষ মিলে বানানো হয়?

Fred Brooks-এর The Mythical Man-Month (১৯৭৫)-এর Brooks's law দুটি খরচের কথা বলে: নতুন মানুষকে শেখাতে পুরোনোদের সময় যায়, আর মানুষ বাড়লে যোগাযোগের পথ বর্গের হারে বাড়ে — ১০ জনে ৪৫টি, ৫০ জনে ১,২২৫টি। Brooks নিজেই বলেছিলেন এটি “অতিসরলীকরণ”, কিন্তু মূল কথাটি টিকে আছে: মানুষ যোগ করা সহজ, সমন্বয় যোগ করা কঠিন।

বড় project এর সমাধান করে মানুষকে কম কথা বলার মতো করে সাজিয়ে। প্রথম কৌশল: ছোট, প্রায়-স্বাধীন দল, প্রত্যেকের দায়িত্ব স্পষ্ট সীমায় — Team Topologies-এর stream-aligned দল ঠিক এটাই, আর দলের মধ্যে সম্পর্ক যতটা সম্ভব “X-as-a-Service”, অর্থাৎ নথি দেখে ব্যবহার, সভা ছাড়া। দ্বিতীয়: system-এর সীমাও সেভাবে কাটা — Conway's law অনুযায়ী দলের সীমা আর module-এর সীমা মিললে এক দলের পরিবর্তনে আরেক দলকে জিজ্ঞেস করতে হয় না। তৃতীয়: যোগাযোগকে asynchronous আর লিখিত করা — interface-এর চুক্তি, API-র reference, ADR — যাতে প্রশ্নের উত্তর একজন মানুষের মাথায় না থেকে একটি পাতায় থাকে।

Linux kernel একটি পরিচিত দৃষ্টান্ত: হাজারো অবদানকারী, কিন্তু কাঠামো স্তরভিত্তিক — subsystem maintainer-রা নিজের অংশের patch নেন, তাঁদের থেকে বড় maintainer-এর কাছে যায়, আর সব যোগাযোগ প্রকাশ্য mailing list-এ লিখিত। প্রত্যেককে সবার সাথে কথা বলতে হয় না।

তবু Brooks-এর সতর্কতা ফুরিয়ে যায়নি। নতুন দল যোগ করলেও শুরুর কয়েক সপ্তাহ উৎপাদন কমে — onboarding নথি আর ভালো test সেই সময় কমায়, শূন্য করে না। আর যে কাজ সত্যিই ভাগ করা যায় না — একটি জটিল algorithm-এর মূল নকশা — সেখানে মানুষ বাড়ানো কোনো কাজেই আসে না।

মূল উপলব্ধি: বড় দল সফল হয় যখন প্রতিটি মানুষের দরকারি যোগাযোগের সংখ্যা ছোট থাকে। দলের গঠন, architecture-এর সীমা আর লিখিত interface — তিনটিই একই সমস্যার তিন দিক।

প্র ০২একটি project-এর license “MIT” থেকে “source-available”-ধাঁচের শর্তে বদলে গেল। এটা কীভাবে সম্ভব, আর ব্যবহারকারী ও অবদানকারীর কী হয়?

গত এক দশকে কিছু কোম্পানি-নেতৃত্বাধীন open-source project-এর নতুন version তাদের license বদলে এমন শর্তে নিয়েছে যা OSI-এর সংজ্ঞায় open source নয় — যেমন “এই কোড দিয়ে প্রতিযোগী cloud সেবা দেওয়া যাবে না”। এর পেছনের যুক্তি সাধারণত: বড় cloud কোম্পানি বিনামূল্যের কোড নিয়ে টাকা কামায়, অথচ মূল উন্নয়নের খরচ বহন করে অন্য কেউ। কোন project কবে কী করেছে, তার বিস্তারিত সূত্রসহ নিজে পড়ে নেবেন; এখানে প্রক্রিয়াটিই মূল বিষয়।

কীভাবে সম্ভব? কপিরাইটের মালিক যেকোনো সময় নতুন version অন্য license-এ দিতে পারেন। কিন্তু যে কোড আগে MIT বা Apache-2.0-এ প্রকাশিত হয়েছে, সেই কপির অনুমতি সাধারণত ফেরত নেওয়া যায় না — তাই প্রায়ই সম্প্রদায় শেষ উন্মুক্ত version থেকে একটি fork বানায় এবং নতুন নামে চালিয়ে যায়। মালিক কে, সেটিই এখানে মূল: যদি সব অবদানকারী CLA দিয়ে প্রতিষ্ঠানকে বিস্তৃত অধিকার দিয়ে থাকেন, প্রতিষ্ঠান একা license বদলাতে পারে। যদি অবদান DCO দিয়ে আসে আর কপিরাইট শত শত মানুষের হাতে ছড়িয়ে থাকে, তাহলে license বদলাতে প্রায় সবার অনুমতি লাগে — বাস্তবে প্রায় অসম্ভব। এজন্যই অনেক অবদানকারী কোম্পানির CLA-কে সন্দেহের চোখে দেখেন।

ব্যবহারকারীর জন্য শিক্ষা: dependency বাছাইয়ে শুধু আজকের license নয়, governance-ও দেখুন — একক কোম্পানির নিয়ন্ত্রণ, নাকি নিরপেক্ষ foundation (যেমন Apache Software Foundation বা Linux Foundation-এর অধীন project). Lockfile আর license scan থাকলে নতুন version-এ license বদলালে CI-তেই ধরা পড়ে, ভুলে upgrade হয় না।

মূল উপলব্ধি: License একটি মুহূর্তের অনুমতি, governance হলো ভবিষ্যতের অনুমতি কে ঠিক করবে তার নিয়ম। একটি dependency-র ঝুঁকি বুঝতে দুটোই পড়তে হয়।

প্র ০৩Linux kernel কেন এখনো GPL-2.0-only, GPL-3.0 নয়? এ থেকে license-এর “or later” ধারা সম্পর্কে কী শেখা যায়?

GPL-এর লেখায় একটি প্রস্তাবিত বাক্য থাকে: “version 2 of the License, or (at your option) any later version”. এটি থাকলে ব্যবহারকারী পরের GPL সংস্করণও বেছে নিতে পারেন। Linux kernel-এর মূল COPYING ফাইল এই “or later” ছাড়াই — শুধু version 2 — আর Linus Torvalds প্রকাশ্যে বহুবার বলেছেন তিনি GPL-3.0-এর কিছু নতুন শর্ত, বিশেষ করে যন্ত্রে বদলানো software বসাতে দেওয়ার বাধ্যবাধকতা (“anti-tivoization”), পছন্দ করেন না।

কিন্তু চাইলেও বদলানো কঠিন। Kernel-এ হাজারো মানুষের কোড, আর কপিরাইট প্রত্যেকের নিজের — কোনো CLA দিয়ে কেন্দ্রীভূত নয়, অবদান আসে DCO দিয়ে। License বদলাতে কার্যত সবার সম্মতি লাগবে, বা যাঁদের সম্মতি মেলে না তাঁদের কোড নতুন করে লিখতে হবে। ফলে GPL-2.0-only একটি স্থায়ী বাস্তবতা।

এর একটি ব্যবহারিক পরিণাম আপনি ওপরের checker-এ দেখেছেন: GPL-2.0-only কোড GPL-3.0 project-এ নেওয়া যায় না, আর উল্টোটাও না। দুটিই copyleft, তবু একে অপরের সাথে মেলে না — কারণ প্রতিটি বলে “বিতরণ করা পুরো কাজ আমার শর্তে”, আর দুই শর্ত আলাদা। FSF নিজেই “or later” রাখার পরামর্শ দেয়, যাতে ভবিষ্যতে এমন দেয়াল না ওঠে; অন্যদিকে কেউ কেউ বলেন, “or later” মানে ভবিষ্যতের একটি অজানা license-এ আগাম সম্মতি দেওয়া — যা FSF-এর ওপর আস্থা চায়। দুই যুক্তিই যুক্তিসঙ্গত; এজন্যই SPDX “-only” আর “-or-later” আলাদা নাম রেখেছে, যাতে অস্পষ্টতা না থাকে।

Kernel আরও একটি জিনিস দেখায়: GPL-2.0 WITH Linux-syscall-note (kernel-এর ফাইলে পুরোনো নামেই লেখা; এখনকার SPDX নামে GPL-2.0-only WITH Linux-syscall-note) — একটি exception, যা বলে kernel-এর system call ব্যবহার করা সাধারণ প্রোগ্রাম kernel-এর “মিলিত কাজ” নয়। SPDX-এর WITH ঠিক এই ধরনের ছাড় লেখার জন্য।

মূল উপলব্ধি: License বেছে নেওয়ার সিদ্ধান্ত প্রায় অপরিবর্তনীয়, বিশেষত অবদানকারী অনেক হলে। প্রথম দিনেই version, “only” বনাম “or later” আর exception ভেবে ঠিক করুন, আর ADR-এ কারণ লিখে রাখুন।

প্র ০৪২০২৪ সালের xz-utils ঘটনা open source-এর maintainer-দের নিয়ে কী শেখায়? এটা কি শুধু নিরাপত্তার গল্প, নাকি দলগত কাজেরও?

২০২৪ সালের মার্চে একজন প্রকৌশলী খেয়াল করেন SSH login-এ অস্বাভাবিক দেরি আর CPU খরচ। খুঁজতে গিয়ে বেরোয়, বহুল ব্যবহৃত compression library xz-utils-এর দুটি নতুন release-এর build প্রক্রিয়ায় সুপরিকল্পিতভাবে একটি backdoor লুকানো ছিল, যা নির্দিষ্ট কিছু Linux distribution-এ SSH server-কে প্রভাবিত করতে পারত। প্রকাশিত বিশ্লেষণ অনুযায়ী, একজন অবদানকারী প্রায় দুই বছর ধরে ধীরে ধীরে আস্থা অর্জন করে maintainer-এর অধিকার পান। ঘটনাটি নিয়ে অনেক প্রকাশ্য বিশ্লেষণ আছে; বিস্তারিত নিজে সূত্র মিলিয়ে পড়বেন।

দলগত কাজের দিক: প্রকাশিত বিবরণে project-টি মূলত একজন স্বেচ্ছাসেবী maintainer চালাতেন — truck factor ১. তিনি প্রকাশ্যে ক্লান্তি আর সময়ের অভাবের কথা লিখেছিলেন, আর সেই সময়ে কয়েকটি অ্যাকাউন্ট থেকে “দ্রুত release দিন, নতুন maintainer নিন” ধরনের চাপ আসছিল — পরে অনেকে সন্দেহ করেন সেগুলোও পরিকল্পনার অংশ। অর্থাৎ আক্রমণ এসেছে একটি মানবিক দুর্বলতা দিয়ে: একা, ক্লান্ত মানুষ আর সাহায্যের সত্যিকার প্রয়োজন।

শিক্ষা: (১) অনেক গুরুত্বপূর্ণ dependency অল্প কয়েকজনের হাতে — অংশ ৫-এর truck factor হিসাব আপনার dependency-তেও চালাতে পারেন। (২) Maintainer-এর অধিকার দেওয়ার স্পষ্ট governance নিয়ম, একাধিক মানুষের review, আর release-এর ফাইল source থেকে নিজে build করে মিলিয়ে দেখা (reproducible build) এমন ঝুঁকি কমায়। (৩) যে কোম্পানি এমন library-র ওপর নির্ভর করে, তারা অর্থ বা কর্মীর সময় দিয়ে maintainer-কে সাহায্য করতে পারে — open source “বিনামূল্যে” হলেও তার রক্ষণাবেক্ষণ বিনামূল্যে নয়। নিরাপত্তার কারিগরি দিক পর্ব ৫৭-এ (Git-এ নিরাপত্তা)।

মূল উপলব্ধি: Software supply chain-এর সবচেয়ে দুর্বল কড়া প্রায়ই কোড নয়, মানুষ — আর মানুষকে রক্ষা করে ভালো governance, ভাগ করা দায়িত্ব আর সহানুভূতিশীল সম্প্রদায়।

প্র ০৫“ভালো কোড নিজেই নিজের নথি” — এই কথা কতটা সত্য? কোন নথি কোড কখনো দিতে পারে না?

কথাটির অর্ধেক সত্য। পর্ব ৪১-এ (Clean code) দেখেছেন, ভালো নাম, ছোট function আর স্পষ্ট গঠন অনেক মন্তব্যের প্রয়োজন মেটায় — “কী করছে” কোড থেকেই পড়া যায়। আর কোডের পাশে লেখা test একরকম চলমান নথি: আচরণ বদলালে test ভাঙে, তাই সেটি পুরোনো হয় না।

কিন্তু Diátaxis-এর চার ভাগে তাকান। Reference-এর বড় অংশ কোড থেকে তৈরি করা যায় — type, signature, docstring. বাকি তিনটি পারে না। Tutorial: একজন নতুন মানুষ কোন ক্রমে শিখবেন, কোথায় সাধারণত আটকান — এটি পাঠকের যাত্রা, কোডের গঠন নয়। How-to: “bKash-এর মতো নতুন gateway যোগ করতে এই তিনটি ফাইল ছুঁতে হবে” — এই জ্ঞান বহু ফাইলে ছড়ানো, কোনো এক জায়গায় লেখা নেই। আর explanation — সবচেয়ে মূল্যবান — “কেন”: কোন বিকল্প বিবেচনা করে বাদ দেওয়া হয়েছিল, কোন সীমাবদ্ধতা তখন ছিল। কোড শুধু টিকে থাকা সিদ্ধান্ত দেখায়; বাতিল সিদ্ধান্ত আর তার কারণ সেখানে অদৃশ্য। ADR ঠিক এই ফাঁক পূরণ করে।

দলের বাইরের নথিও আছে: কীভাবে অবদান রাখবেন, কাকে জিজ্ঞেস করবেন, release কীভাবে হয়, incident হলে কী করবেন। এগুলো প্রক্রিয়া, কোডে নেই। Bus factor-এর হিসাবে দেখেছেন, এই জ্ঞান মানুষের মাথায় থাকলে মানুষ চলে গেলেই হারায়।

উল্টো দিকের সতর্কতাও সত্য: অতিরিক্ত, অযত্নে রাখা নথি ক্ষতিকর, কারণ ভুল পথ দেখায়। তাই নথি কম কিন্তু যত্নে — কোডের সাথে একই PR-এ বদলানো, CI-তে যাচাই, মালিকসহ।

মূল উপলব্ধি: কোড বলে “কী” আর “কীভাবে”; ভালো নথি বলে “কেন”, “কার জন্য” আর “কোন ক্রমে”। এই দুটি একে অপরের বিকল্প নয়, পরিপূরক।

অনুশীলন

হিসাব আর ভবিষ্যদ্বাণী আগে কাগজে করুন, তারপর উত্তর মিলিয়ে দেখুন।

  1. Truck factor হিসাব করুন: একটি ছোট project-এর ৬টি ফাইলে commit-এর সংখ্যা: a.py — Tanvir 10, Mitu 2; b.py — Tanvir 3, Mitu 3; c.py — Mitu 8; d.py — Joy 4, Tanvir 4, Mitu 1; e.py — Joy 5; f.py — Tanvir 6, Joy 1. অংশ ৫-এর নিয়মে (২৫% সীমা, greedy, tie-এ বর্ণানুক্রম, অর্ধেকের বেশি অভিভাবকহীন হলে থামা) truck factor কত? তারপর সীমা ১০% করলে কত হয়?

    ২৫% সীমায় মালিকানা: a — Tanvir (10/12 ≈ ৮৩%; Mitu ১৭%); b — Tanvir, Mitu (৫০% করে); c — Mitu; d — Joy, Tanvir (৪/৯ ≈ ৪৪% করে; Mitu ১১%); e — Joy; f — Tanvir (৬/৭ ≈ ৮৬%; Joy ১৪%). গণনা: Tanvir ৪ (a, b, d, f), Mitu ২ (b, c), Joy ২ (d, e).

    ধাপ: Tanvir সরালে a আর f অভিভাবকহীন — ২/৬, অর্ধেকের (৩) বেশি নয়। এখন Mitu ২ (b, c), Joy ২ (d, e) — tie, বর্ণানুক্রমে Joy. Joy সরালে d আর e যোগ হয় — ৪/৬ > ৩, থামুন। Truck factor = ২.

    ১০% সীমায়: এখন Mitu a-তে (১৭%) আর d-তে (১১%), Joy f-এ (১৪%) গোনা হন। গণনা: Tanvir ৪, Mitu ৪ (a, b, c, d), Joy ৩ (d, e, f). Tie-এ Mitu আগে: সরালে শুধু c অভিভাবকহীন (১/৬)। তারপর Tanvir (৪): a আর b যোগ — ৩/৬, ঠিক অর্ধেক, বেশি নয়। তারপর Joy: d, e, f — ৬/৬. Truck factor = ৩. শিক্ষা: “জানা”-র সংজ্ঞা ঢিলা করলে সংখ্যা বাড়ে — তাই truck factor-এর সাথে সবসময় পদ্ধতি আর সীমা লিখুন। (অংশ ৫-এর Python কোডের commits আর SHARE বদলে নিজে যাচাই করতে পারেন।)

  2. আউটপুট অনুমান করুন: অংশ ৭-এর license_matrix.js-এর asks তালিকা বদলে এই চারটি দেওয়া হলো: ["LGPL-2.1-only", "MIT"], ["GPL-3.0-only", "AGPL-3.0-only"], ["Apache-2.0", "LGPL-2.1-only"], ["GPL-3.0", "GPL-3.0-only"]. চারটি লাইন কী ছাপবে?
    LGPL-2.1-only into MIT          : yes, with conditions on A's part
    GPL-3.0-only  into AGPL-3.0-only: yes (keep copyright and license text)
    Apache-2.0    into LGPL-2.1-only: NO  (needs relicensing or permission)
    GPL-3.0       into GPL-3.0-only : unknown - ask a person who knows

    প্রথমটি LGPL-2.1-only সারির প্রথম অক্ষর C: library-টি LGPL-ই থাকে, আর তার শর্ত (বদলানো library-র source, ব্যবহারকারীর বদলে জোড়ার সুযোগ) মানতে হয়। দ্বিতীয়টি GPL-3.0-only সারির শেষ অক্ষর Y — GPL-3.0-এর ধারা ১৩ AGPL-3.0-এর সাথে মেলাতে দেয়। তৃতীয়টি Apache-2.0 সারির চতুর্থ অক্ষর N — টেবিলের সরল ধারণায় LGPL-2.1 এ বিষয়ে GPL-2.0-এর মতো আচরণ করে (এটি একটি সরলীকরণ; বাস্তব ক্ষেত্রে আইনি দলের সাথে যাচাই করুন)। চতুর্থটি ফাঁদ: GPL-3.0 একটি পুরোনো, deprecated SPDX নাম, টেবিলে নেই — তাই “unknown”. দ্বিতীয় লাইনে padEnd(13): AGPL-3.0-only ঠিক ১৩ অক্ষর, তাই কোলনের আগে ফাঁকা নেই।

  3. README আর CONTRIBUTING-এর রূপরেখা লিখুন: একটি বিশ্ববিদ্যালয়ের ফলাফল পোর্টাল (কাল্পনিক) — Python back-end, PostgreSQL, GPL-3.0-or-later — open source করা হবে। শুধু heading আর প্রতিটির নিচে এক লাইনে কী থাকবে, এভাবে দুটি ফাইলের রূপরেখা লিখুন। তারপর ভাবুন: কোন তথ্য README-তে নয়, অন্য নথিতে যাওয়া উচিত?

    README.md: # result-portal — এক বাক্য: শিক্ষার্থীরা নিজের ফলাফল আর GPA দেখার একটি web portal (কাল্পনিক)। ## Features — ৩–৫টি বুলেট। ## Quick start — প্রয়োজনীয় version (Python, PostgreSQL), clone, virtual environment, pip install -r requirements.txt, নমুনা data দিয়ে database তৈরি, চালানো। ## Usage — একটি screenshot বা নমুনা request. ## Documentation — docs/-এর tutorial, how-to, reference আর ADR-এর link. ## Contributing — এক লাইন আর CONTRIBUTING.md-এর link. ## Security — দুর্বলতা জানাতে SECURITY.md. ## License — GPL-3.0-or-later, LICENSE ফাইল দেখুন।

    CONTRIBUTING.md: ## Code of conduct — link আর অভিযোগের ঠিকানা। ## কোথা থেকে শুরু — good first issue লেবেল, বড় পরিবর্তনে আগে issue. ## Development setup — নমুনা data, test database. ## Tests and lint — কোন command, CI-তে কী চলে। ## Branch and commit — branch-এর নাম, Conventional Commits, DCO-র git commit -s. ## Pull request — template, ছোট PR, review-এর সময়ের প্রত্যাশা। ## Documentation — আচরণ বদলালে নথিও একই PR-এ। ## License of contributions — অবদান GPL-3.0-or-later-এ গৃহীত।

    যা README-তে নয়: পূর্ণ API reference (docs/reference-এ, কোড থেকে তৈরি), নকশার কারণ (ADR-এ), production-এর deployment আর গোপন config (ভেতরের runbook-এ, কখনো public repo-তে নয়), আর আসল শিক্ষার্থীর কোনো data — নমুনা data-ও কাল্পনিক হতে হবে।

  4. Time zone আর সভার নকশা: একটি দলে আছেন ঢাকা (UTC+6, কাজ সকাল ১০টা–সন্ধ্যা ৬টা), Berlin আর Toronto-র সদস্য (দুই শহরে কাজ সকাল ৯টা–বিকেল ৫টা)। শীতকালে Berlin UTC+1, Toronto UTC−5. প্রতিটি জোড়ার একসাথে কাজের সময় কত ঘণ্টা? তিনজনের সাপ্তাহিক সিদ্ধান্তের সভা কীভাবে সাজাবেন?

    UTC-তে রূপান্তর: ঢাকা 10:00–18:00 → UTC 04:00–12:00; Berlin 09:00–17:00 → UTC 08:00–16:00; Toronto 09:00–17:00 → UTC 14:00–22:00.

    জোড়া: ঢাকা–Berlin: UTC 08:00–12:00 = ৪ ঘণ্টা (ঢাকায় 14:00–18:00). Berlin–Toronto: UTC 14:00–16:00 = ২ ঘণ্টা (Berlin 15:00–17:00, Toronto 09:00–11:00). ঢাকা–Toronto: UTC 12:00-এ ঢাকা শেষ, 14:00-এ Toronto শুরু — ০ ঘণ্টা; তিনজনের মিলিত সময়ও শূন্য। (গ্রীষ্মে Berlin UTC+2 আর Toronto UTC−4 হলে ঢাকা–Berlin ৫ ঘণ্টা, Berlin–Toronto ২ ঘণ্টা, ঢাকা–Toronto এখনো ০; আর মার্চ ও অক্টোবর-নভেম্বরে কয়েক সপ্তাহ দুই অঞ্চলের সময় বদলানোর তারিখ মেলে না।)

    নকশা: সিদ্ধান্ত মূলত asynchronous: প্রস্তাব লেখা নথিতে, ৪৮ ঘণ্টার মন্তব্যের সময়, তারপর সিদ্ধান্তদাতা লিখিত সিদ্ধান্ত দেন। Synchronous সভা দরকার হলে মাসে একবার, আর অসুবিধার সময়টা পালা করে — একবার ঢাকার সন্ধ্যা, একবার Toronto-র ভোর — যাতে একজনই সবসময় কষ্ট না করেন। সভা রেকর্ড আর লিখিত সারাংশসহ, যাতে অনুপস্থিতরা পরে মত দিতে পারেন।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি open-source project-এ প্রথম অবদানের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. 🔎 Issue খুঁজে CONTRIBUTING আর code of conduct পড়া
  2. 🍴 Fork, clone আর upstream remote যোগ
  3. 🌿 নতুন branch-এ পরিবর্তন আর test
  4. ✍️ git commit -s দিয়ে sign-off-সহ commit
  5. 📬 নিজের fork-এ push করে PR, বিবরণে Fixes #42
  6. ✅ Review-এর সাড়া দেওয়া, তারপর maintainer-এর merge

Team Topologies-এর কোন ধরনের দল অন্য দলকে কয়েক সপ্তাহ নতুন দক্ষতা (যেমন test automation) শিখিয়ে তারপর সরে যায়?

  • Stream-aligned
  • Enabling
  • Platform
  • Complicated-subsystem

১০টি ফাইলের একটি project-এ সরলীকৃত greedy পদ্ধতিতে সবচেয়ে বেশি ফাইল জানা লেখককে সরালে ৩টি, তার পরের জনকে সরালে মোট ৬টি ফাইলের আর কোনো জানা লেখক থাকে না। থামার শর্ত “অর্ধেকের বেশি ফাইল অভিভাবকহীন” হলে truck factor কত?

  • ১
  • ৬
  • ২
  • ৩

একটি কোম্পানি একটি AGPL-3.0 database-এর source বদলে নিজের server-এ চালায় আর ইন্টারনেটে গ্রাহকদের সেবা দেয়, কিন্তু software-এর কোনো কপি কাউকে দেয় না। AGPL-এর ধারা ১৩ অনুযায়ী প্রচলিত ব্যাখ্যা কী?

  • গ্রাহকদের বদলানো source পাওয়ার সুযোগ দিতে হবে
  • কোনো কপি বিতরণ হয়নি, তাই কোনো শর্ত নেই
  • সেবাটি বিনামূল্যে দিতে হবে
  • কোম্পানির সব software AGPL-এ প্রকাশ করতে হবে

SPDX expression MIT AND Apache-2.0 OR BSD-3-Clause-এর সঠিক অর্থ কোনটি?

  • MIT সবসময়, আর তার সাথে Apache-2.0 বা BSD-3-Clause-এর একটি
  • তিনটিই একসাথে মানতে হবে
  • যেকোনো একটি license বেছে নেওয়া যাবে
  • হয় MIT ও Apache-2.0 দুটি একসাথে, নয়তো শুধু BSD-3-Clause

একটি GPL-3.0-only project-এ কোড আনতে চান। প্রচলিত ব্যাখ্যায় (FSF-এর মত) কোনটি সরাসরি আনা যায় না?

  • MIT license-এর কোড
  • GPL-2.0-only license-এর কোড
  • Apache-2.0 license-এর কোড
  • BSD-3-Clause license-এর কোড

একটি open-source project অবদানকারীদের কাছে প্রতিটি commit-এ Signed-off-by লাইন চায়, আলাদা কোনো চুক্তি স্বাক্ষর ছাড়া। এটি কী?

  • Contributor License Agreement (CLA)
  • Cryptographic commit signature
  • Developer Certificate of Origin (DCO)
  • Code of conduct-এ সম্মতি

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. দল সাজানো architecture সাজানোরই অংশ: feature বনাম component team, আর Team Topologies-এর চার ধরন ও তিন interaction mode — লক্ষ্য দলের cognitive load সীমায় রাখা।
  2. Tuckman-এর ধাপ মোটা দাগের মডেল; psychological safety আর লিখিত নিয়ম দলকে storming থেকে performing-এ নেয়।
  3. Asynchronous আর লিখিত যোগাযোগ আগে; সভায় agenda, সময় আর লিখিত ফল; নথি Diátaxis-এর চার ভাগে, docs-as-code ধারায় কোডের সাথে।
  4. Truck factor commit-এর লেখক থেকে আনুমানিক হিসাব করা যায়; ফলের সাথে পদ্ধতি আর সীমা লিখুন, আর review, pairing ও নথি দিয়ে বাড়ান।
  5. License-এর বর্ণালি permissive → weak → strong → network copyleft; compatibility দিক-নির্ভর; SPDX নাম, NOTICE আর CI-তে scan — আর সন্দেহে আইনি পরামর্শ।

পরের পর্বে: License বলে কী করা যায়; নৈতিকতা প্রশ্ন করে কী করা উচিত। পর্ব ৬৪-এ ACM/IEEE-র code of ethics, ব্যবহারকারীর privacy, accessibility, আর AI-সহায়তায় লেখা কোডে একজন প্রকৌশলীর দায়িত্ব।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান