Object-Oriented Programming Foundations

Packages and Organizing Java Code

ReadingPreview

You are viewing a free preview lesson.

Lesson Overview

একটি Java project শুরুতে খুব ছোট হতে পারে।

Main.java
Course.java
Learner.java
Enrollment.java

কিন্তু application বড় হলে classes বাড়তে থাকে:

Course
Lesson
Module
Learner
Enrollment
Payment
Certificate
Notification
Validation
Repository
Service
Controller

সব classes একই directory বা package-এ রাখলে কয়েকটি সমস্যা হয়:

  • Related code খুঁজে পাওয়া কঠিন হয়
  • Class naming conflict তৈরি হতে পারে
  • Internal implementation unnecessarily visible হয়
  • Responsibilities বোঝা কঠিন হয়
  • পরিবর্তনের impact বুঝতে সময় লাগে
  • Codebase ধীরে ধীরে একটি unstructured collection হয়ে যায়

Java packages related classes organize করতে এবং visibility control করতে সাহায্য করে।

এই lesson-এ আমরা শিখব:

  • Package কী
  • Package declaration
  • Directory এবং package relationship
  • Import statement
  • Same-package access
  • Package-private visibility
  • Public class এবং file organization
  • Package naming conventions
  • Layer-based এবং feature-based organization
  • Maintainable project structure
  • Common package-design mistakes

Learning Objectives

এই lesson শেষ করার পর আপনি পারবেন:

  • Java package-এর purpose ব্যাখ্যা করতে
  • Class-এর package declare করতে
  • Package অনুযায়ী source directory organize করতে
  • অন্য package-এর class import করতে
  • public এবং package-private classes আলাদা করতে
  • Reverse-domain package naming follow করতে
  • Code feature অনুযায়ী organize করতে
  • Large model, service, এবং util packages avoid করতে
  • Package boundaries ব্যবহার করে internal implementation hide করতে
  • একটি ছোট Java application-এর maintainable structure design করতে

What Is a Package?

Package হলো related Java types organize করার একটি namespace।

Types বলতে এখানে বোঝানো হচ্ছে:

  • Classes
  • Interfaces
  • Enums
  • Records
  • Annotations

Example package:

package io.liveklass.course;

এই package-এর মধ্যে course-related classes থাকতে পারে:

Course
Lesson
CourseCode
CourseStatus

আরেকটি package:

package io.liveklass.enrollment;

এর মধ্যে থাকতে পারে:

Enrollment
EnrollmentStatus
EnrollmentService

Why Packages Matter

Packages কয়েকটি গুরুত্বপূর্ণ problem solve করে।

Organization

Related code একই জায়গায় রাখা যায়।

course-related code
enrollment-related code
payment-related code

Namespace

Different packages-এ same class name থাকতে পারে।

io.liveklass.course.Module
java.lang.Module

Visibility

Package-private members শুধু same package-এর code use করতে পারে।

Architecture

Packages codebase-এর responsibilities এবং boundaries communicate করতে পারে।


Declaring a Package

Java source file-এর শুরুতে package declaration লেখা হয়।

package io.liveklass.course;

public class Course {

}

Comments বাদ দিলে package declaration সাধারণত file-এর প্রথম statement।

Order:

Package declaration
Import declarations
Class declaration

Example:

package io.liveklass.enrollment;

import io.liveklass.course.Course;
import io.liveklass.learner.Learner;

public class Enrollment {

}

Package and Directory Structure

Package name সাধারণত source directory structure-এর সঙ্গে match করে।

Package:

package io.liveklass.course;

Expected path:

src/main/java/io/liveklass/course/Course.java

Full example:

src/
└── main/
    └── java/
        └── io/
            └── liveklass/
                └── course/
                    └── Course.java

Course.java:

package io.liveklass.course;

public class Course {

}

Modern IDE এবং build tools এই convention expect করে।


Package Naming Convention

Java package names সাধারণত lowercase হয়।

Correct:

io.liveklass.course
io.liveklass.enrollment
io.liveklass.payment

Avoid:

io.LiveKlass.Course
io.liveklass.CourseManagement
IO.LIVEKLASS.COURSE

Reverse-Domain Naming

Organizations সাধারণত নিজের domain reverse করে root package তৈরি করে।

Domain:

liveklass.io

Root package:

io.liveklass

Examples:

io.liveklass.course
io.liveklass.enrollment
io.liveklass.learner

এটি globally unique naming-এর সম্ভাবনা বাড়ায়।


Avoid the Default Package

Package declaration ছাড়া class default package-এ থাকে।

public class Course {

}

Small disposable example-এ এটি কাজ করতে পারে।

কিন্তু real project-এ default package avoid করা উচিত।

Problems:

  • Named packages থেকে default-package classes import করা যায় না
  • Project organization দুর্বল হয়
  • Framework এবং tooling-এর সঙ্গে সমস্যা হতে পারে
  • Architecture বোঝা কঠিন হয়

Production-oriented code সবসময় named package-এ রাখুন।


Import Statements

অন্য package-এর class simple name দিয়ে ব্যবহার করতে import প্রয়োজন।

Course.java:

package io.liveklass.course;

public class Course {

}

Enrollment.java:

package io.liveklass.enrollment;

import io.liveklass.course.Course;

public class Enrollment {

    private final Course course;

    public Enrollment(
            Course course
    ) {
        this.course = course;
    }
}

Import না করলে fully qualified name ব্যবহার করতে হয়।

private final io.liveklass.course.Course course;

Technically valid, কিন্তু repeated use-এর জন্য import cleaner।


Same Package Does Not Need Import

দুইটি class same package-এ থাকলে import প্রয়োজন নেই।

Course.java:

package io.liveklass.course;

public class Course {

}

CourseCode.java:

package io.liveklass.course;

public final class CourseCode {

}

Course direct CourseCode use করতে পারে।

private final CourseCode code;

No import required।


java.lang Is Imported Automatically

Common classes automaticভাবে available:

String
Object
Integer
System
Math

কারণ java.lang package automatically imported।

এ জন্য লিখতে হয় না:

import java.lang.String;

Wildcard Imports

Example:

import java.util.*;

এটি java.util package-এর accessible types import করতে পারে।

তবে production code-এ explicit imports সাধারণত clearer।

Prefer:

import java.util.ArrayList;
import java.util.List;

Benefits:

  • কোন types use হচ্ছে immediately বোঝা যায়
  • Same-name class conflict clearer হয়
  • Code review সহজ হয়

Most IDE imports automatically manage করতে পারে।


Wildcards Do Not Import Subpackages

import java.util.*;

এটি import করে না:

java.util.concurrent
java.util.function

Subpackages independent packages।

প্রয়োজনে:

import java.util.concurrent.atomic.AtomicInteger;

Classes with the Same Name

Suppose:

io.liveklass.course.Module
java.lang.Module

Same file-এ দুইটি simple name একসঙ্গে import করা যাবে না।

একটিকে fully qualified name দিয়ে use করতে হবে।

io.liveklass.course.Module courseModule;
java.lang.Module javaModule;

Strong naming conflict avoid করার আরেকটি উপায় হলো domain class-এর more specific name ব্যবহার করা।

CourseModule

এটি অনেক ক্ষেত্রে clearer।


Public Top-Level Classes and File Names

A public top-level class-এর file name class name-এর সঙ্গে match করতে হয়।

public class Course {

}

File:

Course.java

Wrong:

CourseModel.java

যদি class declaration হয়:

public class Course

One Public Top-Level Class per File

একটি source file-এ সর্বোচ্চ একটি public top-level class থাকতে পারে।

Valid:

public class Course {

}

class CourseValidator {

}

এখানে CourseValidator package-private।

তবে unrelated top-level classes একই file-এ রাখা readability কমাতে পারে।

Practical rule:

একটি meaningful top-level type সাধারণত নিজের file-এ রাখুন।

Small private helper type exception হতে পারে।


Package-Private Classes

কোনো top-level class-এর আগে access modifier না দিলে সেটি package-private।

package io.liveklass.course;

final class CourseTitleValidator {

}

এটি শুধু io.liveklass.course package-এর classes use করতে পারবে।

অন্য package থেকে:

import io.liveklass.course.CourseTitleValidator;

করতে গেলে access error হবে।


Package-Private Members

Member-এর আগে modifier না থাকলেও package-private হয়।

class CourseDraft {

    String title;

    void validate() {
    }
}

Same package access করতে পারে।

Other package পারে না।

Package-private useful যখন implementation:

  • Package-এর internal detail
  • Public API-এর অংশ নয়
  • Closely collaborating classes-এর জন্য প্রয়োজন

Package Is Not a Security Boundary

private এবং package-private compile-time access control দেয়।

এগুলো cryptographic বা runtime security boundary নয়।

Reflection, serialization tools, frameworks, এবং JVM-level capabilities access behavior influence করতে পারে।

Therefore:

Package visibility code organization এবং encapsulation-এর tool; sensitive data security mechanism নয়।

Passwords বা secrets package-private রাখলেই secure হয় না।


Public API and Internal Implementation

Suppose course creation-এর public API:

public class Course {

    public Course(
            CourseCode code,
            String title
    ) {
    }

    public boolean publish() {
        return true;
    }
}

Internal validator:

final class CourseValidator {

    static void validateTitle(
            String title
    ) {
    }
}

CourseValidator public হওয়ার প্রয়োজন নেই।

External callers শুধু stable domain API দেখবে।

Course
CourseCode

Implementation detail package-এর ভেতরে hidden থাকে।


Package Cohesion

একটি package-এর classes ideally related responsibility share করে।

Good:

io.liveklass.course

Course
CourseCode
CourseStatus
CourseRepository
CourseService

Potentially weak:

io.liveklass.common

Course
Payment
EmailSender
StringUtils
Enrollment
DatabaseHelper

common package দ্রুত unrelated code-এর dumping ground হয়ে যেতে পারে।


Organizing by Technical Layer

Layer-based structure:

io.liveklass.controller
io.liveklass.service
io.liveklass.repository
io.liveklass.model

Example:

controller/
    CourseController
    EnrollmentController

service/
    CourseService
    EnrollmentService

repository/
    CourseRepository
    EnrollmentRepository

model/
    Course
    Enrollment

Small application-এ এটি understandable।

কিন্তু application বড় হলে একটি feature change করতে multiple distant packages navigate করতে হয়।


Organizing by Feature

Feature-based structure:

io.liveklass.course
io.liveklass.enrollment
io.liveklass.learner
io.liveklass.payment

Inside a feature:

course/
    Course
    CourseCode
    CourseService
    CourseRepository
    CourseController

Enrollment:

enrollment/
    Enrollment
    EnrollmentService
    EnrollmentRepository
    EnrollmentController

Benefits:

  • Related code কাছাকাছি থাকে
  • Feature ownership clearer হয়
  • Changes-এর impact বুঝতে সহজ
  • Internal classes package-private রাখা যায়
  • Large codebase navigate করা সহজ

Feature Packages Can Have Internal Layers

Feature-based organization মানে layer বাদ দেওয়া নয়।

Example:

io.liveklass.course
├── api
│   └── CourseController
├── application
│   └── CourseService
├── domain
│   ├── Course
│   └── CourseCode
└── infrastructure
    └── PostgresCourseRepository

এই structure larger feature-এর জন্য useful।

কিন্তু ছোট feature-এর জন্য unnecessary nesting avoid করুন।

Simple শুরু করুন:

io.liveklass.course

Complexity real প্রয়োজন অনুযায়ী add করুন।


A Practical Small-Project Structure

src/main/java/io/liveklass/
├── Main.java
├── course/
│   ├── Course.java
│   └── CourseCode.java
├── learner/
│   └── Learner.java
└── enrollment/
    └── Enrollment.java

এটি beginner project-এর জন্য যথেষ্ট clear।


Package Example: Course

Path:

src/main/java/io/liveklass/course/Course.java
package io.liveklass.course;

public class Course {

    private final CourseCode code;
    private final String title;
    private final int totalLessons;

    private boolean published;

    public Course(
            CourseCode code,
            String title,
            int totalLessons
    ) {
        if (code == null) {
            throw new IllegalArgumentException(
                    "Course code is required."
            );
        }

        if (
                title == null
                || title.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Course title is required."
            );
        }

        if (totalLessons <= 0) {
            throw new IllegalArgumentException(
                    "Total lessons must be greater than zero."
            );
        }

        this.code = code;
        this.title = title.strip();
        this.totalLessons =
                totalLessons;

        this.published = false;
    }

    public boolean publish() {
        if (published) {
            return false;
        }

        published = true;

        return true;
    }

    public CourseCode getCode() {
        return code;
    }

    public String getTitle() {
        return title;
    }

    public int getTotalLessons() {
        return totalLessons;
    }

    public boolean isPublished() {
        return published;
    }
}

Package Example: CourseCode

Path:

src/main/java/io/liveklass/course/CourseCode.java
package io.liveklass.course;

import java.util.Objects;

public final class CourseCode {

    private final String value;

    public CourseCode(
            String value
    ) {
        if (
                value == null
                || value.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Course code is required."
            );
        }

        this.value =
                value.strip()
                        .toUpperCase();
    }

    public String getValue() {
        return value;
    }

    @Override
    public boolean equals(
            Object other
    ) {
        if (this == other) {
            return true;
        }

        if (
                other == null
                || getClass()
                != other.getClass()
        ) {
            return false;
        }

        CourseCode that =
                (CourseCode) other;

        return value.equals(
                that.value
        );
    }

    @Override
    public int hashCode() {
        return Objects.hash(
                value
        );
    }

    @Override
    public String toString() {
        return value;
    }
}

Package Example: Learner

Path:

src/main/java/io/liveklass/learner/Learner.java
package io.liveklass.learner;

public class Learner {

    private final long id;
    private final String name;

    public Learner(
            long id,
            String name
    ) {
        if (id <= 0) {
            throw new IllegalArgumentException(
                    "Learner ID must be positive."
            );
        }

        if (
                name == null
                || name.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Learner name is required."
            );
        }

        this.id = id;
        this.name = name.strip();
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

Package Example: Enrollment

Path:

src/main/java/io/liveklass/enrollment/Enrollment.java
package io.liveklass.enrollment;

import io.liveklass.course.Course;
import io.liveklass.learner.Learner;

public class Enrollment {

    private final Learner learner;
    private final Course course;

    private int completedLessons;

    public Enrollment(
            Learner learner,
            Course course
    ) {
        if (learner == null) {
            throw new IllegalArgumentException(
                    "Learner is required."
            );
        }

        if (course == null) {
            throw new IllegalArgumentException(
                    "Course is required."
            );
        }

        if (!course.isPublished()) {
            throw new IllegalArgumentException(
                    "Course must be published."
            );
        }

        this.learner = learner;
        this.course = course;
        this.completedLessons = 0;
    }

    public boolean completeLessons(
            int lessonCount
    ) {
        if (lessonCount <= 0) {
            return false;
        }

        int updatedCount =
                completedLessons
                + lessonCount;

        if (
                updatedCount
                > course.getTotalLessons()
        ) {
            return false;
        }

        completedLessons =
                updatedCount;

        return true;
    }

    public double calculateProgress() {
        return completedLessons
                * 100.0
                / course.getTotalLessons();
    }

    public Learner getLearner() {
        return learner;
    }

    public Course getCourse() {
        return course;
    }
}

Package Example: Main

Path:

src/main/java/io/liveklass/Main.java
package io.liveklass;

import io.liveklass.course.Course;
import io.liveklass.course.CourseCode;
import io.liveklass.enrollment.Enrollment;
import io.liveklass.learner.Learner;

public class Main {

    public static void main(
            String[] args
    ) {
        Course course =
                new Course(
                        new CourseCode(
                                "java-foundation"
                        ),
                        "Java and OOP Foundation",
                        20
                );

        course.publish();

        Learner nur =
                new Learner(
                        1L,
                        "Nur"
                );

        Enrollment enrollment =
                new Enrollment(
                        nur,
                        course
                );

        enrollment.completeLessons(
                8
        );

        System.out.println(
                "Learner: "
                + enrollment
                        .getLearner()
                        .getName()
        );

        System.out.println(
                "Course: "
                + enrollment
                        .getCourse()
                        .getTitle()
        );

        System.out.println(
                "Progress: "
                + "%.2f%%".formatted(
                        enrollment
                                .calculateProgress()
                )
        );
    }
}

Compiling Packaged Classes

Source root-এ থেকে compile করা যায়:

javac -d out \
    src/main/java/io/liveklass/course/CourseCode.java \
    src/main/java/io/liveklass/course/Course.java \
    src/main/java/io/liveklass/learner/Learner.java \
    src/main/java/io/liveklass/enrollment/Enrollment.java \
    src/main/java/io/liveklass/Main.java

-d out compiled classes package directory অনুযায়ী out-এ রাখে।

Run:

java -cp out io.liveklass.Main

Notice:

io.liveklass.Main

Fully qualified class name ব্যবহার করা হয়েছে।

Production project-এ Maven বা Gradle compilation manage করে।


Fully Qualified Class Name

একটি class-এর complete name হলো:

package name + class name

Example:

io.liveklass.course.Course

এটিকে fully qualified class name বলা হয়।

Simple class name:

Course

Avoid Generic model Packages

Package:

io.liveklass.model

শুরুতে convenient মনে হয়।

কিন্তু সময়ের সঙ্গে এতে থাকতে পারে:

Course
Learner
Enrollment
Payment
Notification
Certificate

এগুলো related feature নয়।

Better:

io.liveklass.course.Course
io.liveklass.learner.Learner
io.liveklass.enrollment.Enrollment

Domain ownership clearer থাকে।


Avoid Giant util Packages

util package দ্রুত miscellaneous functions-এর collection হতে পারে।

StringUtils
CourseUtils
DateUtils
PaymentUtils
CommonUtils
Helper
GeneralHelper

Before creating utility class, ask:

  • Methodটি কি কোনো domain object-এর behavior?
  • Existing standard library method আছে?
  • একটি focused service বা value object better?
  • Utility class-এর clear responsibility আছে?

Focused utility:

MoneyFormatter
CourseCodeParser

Generic utility:

AppUtils
CommonHelper

avoid করা ভালো।


Avoid Package Names Based on Temporary Roles

Names:

misc
temp
common
helpers
others

Package responsibility communicate করে না।

Better package name domain বা technical purpose clearly express করবে।

course
enrollment
payment
notification

Keep Dependency Direction Clear

Suppose:

enrollment depends on course
enrollment depends on learner

Imports:

import io.liveklass.course.Course;
import io.liveklass.learner.Learner;

Avoid accidental circular package dependency:

course imports enrollment
enrollment imports course

Circular dependencies code boundaries unclear করতে পারে।

Not every two-way reference wrong, কিন্তু dependency direction deliberate হওয়া উচিত।


Package Boundaries and Public Types

যদি সব classes public হয়, package internal implementation hide করতে পারে না।

Example:

Course
CourseValidator
CourseMapper
CoursePersistenceModel
CourseRowParser

External packages-এর সম্ভবত শুধু প্রয়োজন:

Course
CourseService

Others package-private হতে পারে।

Small stable public surface future refactoring সহজ করে।


Engineering Note: Package by Feature Is Not a Universal Rule

Feature-based organization larger business applications-এ অনেক সময় effective।

তবে technical libraries-এর জন্য layer বা capability-based packages natural হতে পারে।

Example:

com.example.json
com.example.http
com.example.crypto

A compiler project may organize by:

lexer
parser
ast
optimizer
codegen

Best structure domain এবং change patterns-এর ওপর depend করে।

Strong rule:

যেসব classes সাধারণত একসঙ্গে পরিবর্তিত হয়, সেগুলো কাছাকাছি রাখুন।


Engineering Note: Package Renaming Is an Architectural Change

Package rename শুধু folder move নয়।

এটি affect করতে পারে:

  • Imports
  • Reflection-based class names
  • Serialization configuration
  • Framework component scanning
  • Module exports
  • External library users
  • Persisted type identifiers

নিজস্ব internal application-এ rename manageable।

Published library API-তে package names compatibility contract-এর অংশ।


Common Mistakes

Package Path and Declaration Mismatch

File path:

io/liveklass/course/Course.java

Declaration:

package io.liveklass.payment;

Tooling এবং compilation confusing হবে।


Using Uppercase Package Names

package io.liveklass.Course;

Java convention follow করে না।


Keeping Production Classes in the Default Package

Imports এবং project organization দুর্বল হয়।


Importing Unused Classes

Unused imports code clutter করে এবং compiler warning বা style failure তৈরি করতে পারে।

IDE দিয়ে remove করুন।


Using Wildcard Imports Everywhere

Class origins এবং conflicts unclear হতে পারে।


Making All Classes Public

Internal implementation external dependency হয়ে যেতে পারে।


Creating Giant model, service, or util Packages

Feature boundaries disappear হয়।


Over-Nesting Small Projects

course/domain/model/entity/value/internal/core

একটি দুই-class feature-এর জন্য unnecessary complexity।


Circular Package Dependencies

Features tightly coupled হয় এবং independent evolution কঠিন হয়।


Practice Exercises

Exercise 1: Create Package Declarations

নিচের classes appropriate packages-এ রাখুন:

Course
CourseCode
Learner
Enrollment
Payment

Root package:

io.liveklass

প্রতিটির package declaration লিখুন।


Exercise 2: Write Imports

Enrollment uses:

Course
Learner

Their packages:

io.liveklass.course
io.liveklass.learner

Required imports লিখুন।


Exercise 3: Refactor a Layer-Based Structure

Current:

model/
    Course
    Enrollment
    Learner

service/
    CourseService
    EnrollmentService

repository/
    CourseRepository
    EnrollmentRepository

Feature-based structure-এ reorganize করুন।


Exercise 4: Choose Visibility

Appropriate visibility নির্বাচন করুন:

  1. Course used by other features
  2. Internal CourseValidator
  3. Public publish() operation
  4. Internal helper method used only by Course
  5. Internal mapper used only inside the course package

Exercise 5: Find Package Smells

Review:

io.liveklass.common
├── Course
├── PaymentUtils
├── GeneralHelper
├── Enrollment
├── StringUtils
└── NotificationService

Problems identify করুন এবং better structure propose করুন।


Exercise 6: Dependency Direction

Suppose:

Enrollment needs Course
Course does not need Enrollment

Which package should import which?

Explain why unnecessary reverse dependency avoid করা উচিত।


Exercise 7: Small vs Large Feature

Design package structure for:

  1. A small console project with four domain classes
  2. A larger web application with API, application, domain, and infrastructure code

Avoid unnecessary nesting in the small project।


Predict the Result

Question 1

Does this class require an import for String?

package io.liveklass.course;

public class Course {

    private String title;
}

Question 2

Do two classes in the same package require imports for each other?


Question 3

Can another package access this class?

package io.liveklass.course;

final class CourseValidator {

}

Question 4

Does this wildcard import include java.util.concurrent.AtomicInteger?

import java.util.*;

Question 5

What is the fully qualified name?

package io.liveklass.enrollment;

public class Enrollment {

}

Predict the Result Answers

Answer 1

না।

String java.lang package থেকে automaticভাবে available।

Answer 2

না।

Same-package types direct use করা যায়।

Answer 3

না।

Classটি package-private।

Answer 4

না।

Wildcard import subpackages import করে না।

Answer 5

io.liveklass.enrollment.Enrollment

Knowledge Check

Question 1

Java package কী?

Question 2

Package declaration source file-এর কোথায় থাকে?

Question 3

Package name এবং source directory-এর relationship কী?

Question 4

Import statement কেন প্রয়োজন?

Question 5

Same-package class import করতে হয় কি?

Question 6

java.lang package manually import করতে হয় কি?

Question 7

Package-private class কী?

Question 8

Public top-level class-এর file name কী হতে হয়?

Question 9

Reverse-domain naming কী?

Question 10

Default package production project-এ avoid করা উচিত কেন?

Question 11

Feature-based organization-এর benefit কী?

Question 12

Giant util বা common package problematic কেন?

Question 13

Package visibility কি security boundary?

Question 14

সব classes public করা উচিত কি?


Knowledge Check Answers

Answer 1

Related Java types organize এবং namespace করার mechanism।

Answer 2

Comments বাদ দিলে সাধারণত file-এর প্রথম statement হিসেবে।

Answer 3

Package segments সাধারণত nested source directories-এর সঙ্গে match করে।

Answer 4

অন্য package-এর type simple name দিয়ে use করতে।

Answer 5

না।

Answer 6

না। এটি automaticভাবে imported।

Answer 7

কোনো top-level access modifier ছাড়া class, যা শুধু same package থেকে accessible।

Answer 8

Public class name-এর সঙ্গে match করতে হয়।

Answer 9

Organization domain reverse করে root package তৈরি করা।

liveklass.io → io.liveklass

Answer 10

Import limitations, poor organization এবং tooling problems তৈরি করতে পারে।

Answer 11

Related feature code কাছাকাছি থাকে এবং change impact বুঝতে সহজ হয়।

Answer 12

Unrelated responsibilities এক জায়গায় জমে এবং ownership unclear হয়।

Answer 13

না। এটি code-level visibility এবং organization mechanism।

Answer 14

না। External callers-এর প্রয়োজনীয় stable types public হওয়া উচিত; internal implementation package-private বা private রাখা যায়।


Lesson Summary

এই lesson-এ আমরা শিখেছি:

  • Packages related Java types organize করে
  • Package namespace এবং visibility boundary দেয়
  • Package declaration source file-এর শুরুতে থাকে
  • Directory structure package name follow করে
  • Package names lowercase হওয়া উচিত
  • Reverse-domain convention globally distinctive root package দেয়
  • Production code default package avoid করে
  • Imports অন্য package-এর classes use করতে দেয়
  • Same-package classes import প্রয়োজন করে না
  • java.lang automaticভাবে imported
  • Wildcard imports subpackages include করে না
  • Public class file name class name-এর সঙ্গে match করে
  • Package-private types internal implementation hide করতে পারে
  • Packages security boundary নয়
  • Public API small এবং intentional রাখা ভালো
  • Feature-based organization related changes কাছাকাছি রাখে
  • Small project-এ unnecessary package nesting avoid করা উচিত
  • Large feature internal layers ব্যবহার করতে পারে
  • Giant model, common, এবং util packages code ownership দুর্বল করে
  • Dependency direction deliberate হওয়া উচিত
  • Circular package dependencies coupling বাড়াতে পারে
  • Package structure codebase-এর architecture communicate করে
  • যেসব classes একসঙ্গে পরিবর্তিত হয়, সেগুলো কাছাকাছি রাখা maintainability improve করে

Next Lesson

পরবর্তী lesson:

Module Practice: Build a Course Enrollment System

আমরা একটি complete console-based domain model তৈরি করব:

  • CourseCode
  • Course
  • Learner
  • Enrollment
  • Encapsulation
  • Constructors
  • Validation
  • Composition
  • Immutable value objects
  • Equality
  • Static factory methods
  • Package organization
  • Meaningful state transitions