Object-Oriented Programming Foundations
Packages and Organizing Java Code
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, এবংutilpackages 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 নির্বাচন করুন:
Courseused by other features- Internal
CourseValidator - Public
publish()operation - Internal helper method used only by
Course - 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:
- A small console project with four domain classes
- 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.langautomaticভাবে 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, এবংutilpackages 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 তৈরি করব:
CourseCodeCourseLearnerEnrollment- Encapsulation
- Constructors
- Validation
- Composition
- Immutable value objects
- Equality
- Static factory methods
- Package organization
- Meaningful state transitions