Object-Oriented Programming Foundations

Object References, `null`, Identity, Equality, and `toString()`

ReadingPreview

আপনি একটি free preview lesson দেখছেন।

Lesson Overview

Java-তে object variable সাধারণত object নিজে ধারণ করে না।

এটি object-এর একটি reference ধারণ করে।

Course javaCourse =
        new Course(
                "JAVA-FOUNDATION",
                "Java and OOP Foundation"
        );

এখানে:

javaCourse

একটি reference variable।

new Course(...)

একটি object তৈরি করেছে।

Reference এবং object-এর পার্থক্য না বুঝলে কয়েকটি common problem হয়:

  • একটি reference দিয়ে change করলে অন্য reference-এও change দেখা যায়
  • Assignment-কে object copy মনে হয়
  • null থেকে NullPointerException হয়
  • == দিয়ে object content compare করা হয়
  • equals() এবং hashCode() inconsistent হয়
  • Debugging output meaningful হয় না

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

  • Object reference কী
  • Multiple references একই object point করলে কী হয়
  • Reference reassignment
  • null
  • NullPointerException
  • Object identity
  • Reference equality এবং logical equality
  • == এবং equals()
  • hashCode() contract
  • Meaningful toString()
  • Equality design-এর practical rules

Learning Objectives

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

  • Object এবং object reference আলাদা করতে
  • Shared reference বা aliasing ব্যাখ্যা করতে
  • Reference assignment এবং object copying-এর পার্থক্য বুঝতে
  • null safely handle করতে
  • NullPointerException-এর common কারণ identify করতে
  • == এবং equals() সঠিকভাবে ব্যবহার করতে
  • Logical equality-এর জন্য stable identity নির্বাচন করতে
  • equals() এবং hashCode() একসঙ্গে implement করতে
  • Useful এবং safe toString() লিখতে

Object Reference

Object তৈরি করার একটি familiar statement:

Course javaCourse =
        new Course(
                "JAVA-FOUNDATION",
                "Java and OOP Foundation"
        );

এখানে তিনটি গুরুত্বপূর্ণ অংশ আছে:

Course

Reference type।

javaCourse

Reference variable।

new Course(...)

নতুন object তৈরি করে।

Conceptually:

javaCourse
    │
    └──> Course object

Reference ব্যবহার করে object-এর methods call করা হয়।

javaCourse.publish();

Reference Assignment

Consider:

Course selectedCourse =
        javaCourse;

এখানে নতুন Course object তৈরি হয়নি।

শুধু reference value copy হয়েছে।

javaCourse
      │
      ├──> Same Course object
      │
selectedCourse

এখন দুইটি variables একই object refer করছে।


Shared References and Aliasing

একই object-এর multiple references থাকাকে aliasing বলা হয়।

Course firstReference =
        new Course(
                "JAVA-FOUNDATION",
                "Java Foundation"
        );

Course secondReference =
        firstReference;

তারপর:

secondReference.changeTitle(
        "Java and OOP Foundation"
);

Now:

System.out.println(
        firstReference.getTitle()
);

Output:

Java and OOP Foundation

কারণ firstReference এবং secondReference same object point করছে।


Reference Assignment Is Not Object Copying

এই code object copy করে না:

Course secondCourse =
        firstCourse;

Separate object দরকার হলে নতুন object create করতে হবে।

Course secondCourse =
        new Course(
                firstCourse.getCode(),
                firstCourse.getTitle()
        );

এখন দুইটি object আছে।

তবে একই values ব্যবহার করে new object তৈরি করলেই সেটি domain perspective-এ valid copy হবে—এমন নয়।

Copying strategy depend করতে পারে:

  • Identity copy করা যাবে কি না
  • Mutable state কীভাবে copy হবে
  • Nested objects share হবে নাকি copy হবে
  • Audit fields preserve হবে কি না

Copy constructor বা copy factory future design topic হতে পারে।


Reassigning a Reference

Course course =
        new Course(
                "JAVA-FOUNDATION",
                "Java Foundation"
        );

course =
        new Course(
                "BACKEND",
                "Backend Development"
        );

এখন course দ্বিতীয় object point করছে।

প্রথম object-এর অন্য কোনো reachable reference না থাকলে সেটি garbage collection-এর জন্য eligible হতে পারে।

Important:

Reference reassign করা object change করা নয়। Variableটি অন্য object point করা শুরু করে।


Passing References to Methods

Java object reference value-এর একটি copy method-এ pass করে।

static void publishCourse(
        Course course
) {
    course.publish();
}

Call:

publishCourse(
        javaCourse
);

Caller এবং method parameter same object access করে।

তাই object mutation caller থেকে visible।


Reassigning a Method Parameter

static void replaceCourse(
        Course course
) {
    course =
            new Course(
                    "NEW",
                    "New Course"
            );
}

Call:

Course original =
        new Course(
                "JAVA",
                "Java Foundation"
        );

replaceCourse(original);

original এখনও original object point করে।

কারণ method শুধু তার local reference copy reassign করেছে।


What Is null?

null মানে একটি reference কোনো object point করছে না।

Course course = null;

Conceptually:

course ──> no object

null কোনো empty Course object নয়।

এটি object-এর absence represent করে।


NullPointerException

যদি null reference দিয়ে instance member access করা হয়:

Course course = null;

course.publish();

Runtime-এ:

NullPointerException

কারণ method call করার মতো কোনো object নেই।

Same risk:

course.getTitle();
course.changeTitle("Java");

Common Sources of null

null আসতে পারে:

  • Field initialize না হলে
  • Method optional result হিসেবে null return করলে
  • Collection search result না পেলে
  • External data missing হলে
  • Reference manually null assign করলে
  • Dependency properly initialize না হলে

Example:

private Course selectedCourse;

Object তৈরি হলে selectedCourse defaultভাবে null


Basic Null Check

if (course != null) {
    course.publish();
}

Alternative:

if (course == null) {
    return;
}

course.publish();

Early return nesting কমায়।


Null Check Is Not Always the Best Design

Application-এর সব জায়গায় এমন code থাকলে:

if (course != null) {
}

এটি indicate করতে পারে object lifecycle unclear।

Better design হতে পারে:

  • Constructor-এ required dependency নেওয়া
  • Missing value boundary-তে handle করা
  • Empty collection return করা
  • Optional ব্যবহার করা যেখানে absence meaningful
  • Null values domain object-এর ভেতরে না ঢুকতে দেওয়া

Important principle:

Required values-এর absence যত দ্রুত সম্ভব reject করুন।


Comparing with null

null comparison-এর জন্য == এবং != সঠিক।

if (course == null) {
}
if (course != null) {
}

এখানে equals() call করা উচিত নয়।

Wrong:

if (course.equals(null)) {
}

যদি course null হয়, callটি নিজেই NullPointerException দেবে।


Object Identity

Identity নির্ধারণ করে আমরা কোন specific object বা domain entity-এর সঙ্গে কাজ করছি।

Java memory perspective-এ দুইটি separately created objects-এর identity আলাদা।

Course first =
        new Course(
                "JAVA",
                "Java Foundation"
        );

Course second =
        new Course(
                "JAVA",
                "Java Foundation"
        );

Even though values same, objects separately created।


Reference Equality with ==

Objects-এর ক্ষেত্রে == check করে:

দুইটি references কি exact same object point করছে?

System.out.println(
        first == second
);

Output:

false

কারণ two separate objects।


Same Reference with ==

Course first =
        new Course(
                "JAVA",
                "Java Foundation"
        );

Course second =
        first;

System.out.println(
        first == second
);

Output:

true

দুই references same object point করে।


Logical Equality

Logical equality domain rules অনুযায়ী decide করে দুইটি objects same entity বা same value represent করছে কি না।

Example:

Course code: JAVA

যদি course code unique এবং stable হয়, তাহলে একই code থাকা দুইটি Course objects logically same course represent করতে পারে।

Course first =
        new Course(
                "JAVA",
                "Java Foundation"
        );

Course second =
        new Course(
                "JAVA",
                "Java and OOP Foundation"
        );

Titles different হলেও course code same।

Domain rule হতে পারে:

Course identity is determined by course code.

Then:

first.equals(second)

should return:

true

Default equals() Behavior

যদি class equals() override না করে, Object class-এর default implementation reference identity compare করে।

Conceptually, এটি ==-এর মতো behavior দেয়।

Course first =
        new Course(
                "JAVA",
                "Java Foundation"
        );

Course second =
        new Course(
                "JAVA",
                "Java Foundation"
        );

System.out.println(
        first.equals(second)
);

Custom equals() না থাকলে result:

false

Overriding equals()

Logical equality define করতে equals() override করা যায়।

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

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

    Course course =
            (Course) other;

    return code.equals(
            course.code
    );
}

Step by step বুঝি।


Step 1: Same Object Check

if (this == other) {
    return true;
}

একটি object নিজের সঙ্গে অবশ্যই equal।

এটি fast path।


Step 2: Null and Type Check

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

Rules:

  • কোনো object null-এর equal নয়
  • Different class-এর object এই equality strategy-তে equal নয়

Step 3: Cast

Course course =
        (Course) other;

Type check-এর পরে other safely Course হিসেবে cast করা যায়।


Step 4: Compare Identity Field

return code.equals(
        course.code
);

Equality course code-এর ওপর based।

Title বা published state compare করা হয়নি।


Choosing Equality Fields

Equality fields select করা গুরুত্বপূর্ণ design decision।

Good candidates সাধারণত:

  • Stable
  • Meaningful
  • Unique বা identity-defining
  • Object lifetime-এ unchanged

Course example:

courseCode

Potentially weak equality fields:

title
published
price
lessonCount

এগুলো change হতে পারে এবং multiple courses-এ same হতে পারে।


Mutable Fields in Equality

Suppose equality uses title:

return title.equals(
        course.title
);

তারপর title change হলো।

course.changeTitle(
        "Modern Java"
);

Object-এর equality এবং hash code change হয়ে যেতে পারে।

Hash-based collection-এ object থাকলে এটি serious bug তৈরি করতে পারে।

Practical rule:

Equality এবং hashCode()-এ mutable fields ব্যবহার করা carefully avoid করুন।


The equals() Contract

একটি correct equals() implementation-এর properties:

Reflexive

x.equals(x)

must be true

Symmetric

যদি:

x.equals(y)

true হয়, তাহলে:

y.equals(x)

true হতে হবে।

Transitive

যদি:

x equals y
y equals z

তাহলে:

x equals z

হতে হবে।

Consistent

Relevant state unchanged থাকলে repeated calls same result দেবে।

Non-null

x.equals(null)

must be false


hashCode()

equals() override করলে hashCode()-ও override করতে হয়।

Contract:

যদি দুইটি objects equals() অনুযায়ী equal হয়, তাদের hash code অবশ্যই same হতে হবে।

The reverse is not required।

Same hash code থাকা two objects unequal হতে পারে। এটিকে collision বলা হয়।


Implementing hashCode()

@Override
public int hashCode() {
    return code.hashCode();
}

Or:

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

Required import:

import java.util.Objects;

Why hashCode() Matters

Hash-based collections use hashCode():

HashSet
HashMap

Future collections lesson-এ এগুলো বিস্তারিত শেখানো হবে।

যদি equals() logical equality define করে কিন্তু hashCode() old identity-based behavior রাখে, equal objects different hash buckets-এ যেতে পারে।

Result:

  • Duplicate values HashSet-এ থাকতে পারে
  • HashMap lookup fail করতে পারে
  • Collection behavior inconsistent হয়

Rule:

Override equals() and hashCode() together.


Using Objects.equals()

Nullable values compare করতে:

Objects.equals(
        firstValue,
        secondValue
);

Behavior:

Both null        → true
One null         → false
Both non-null    → firstValue.equals(secondValue)

Example:

return Objects.equals(
        code,
        course.code
);

যদি constructor code কখনো null হতে না দেয়, direct code.equals(...) safe।

Objects.equals() null-safe comparison-এর জন্য useful।


Equality Strategy Is a Domain Decision

সব classes একইভাবে equality define করবে না।

Value Object

Example:

Money
EmailAddress
Coordinates

সব meaningful values equality-তে অংশ নিতে পারে।

Entity

Example:

Course
Learner
Enrollment

Stable identity field equality define করতে পারে।

Simple Data Transfer Object

সব fields compare করা useful হতে পারে।

No universal rule:

Always compare all fields

বা:

Always compare database ID

দুটিই oversimplification।


Engineering Note: Database-Generated IDs

Production entity-এর ID database insert-এর পরে assign হতে পারে।

Before persistence:

id = null

After persistence:

id = 1042

যদি equality শুধু database ID-এর ওপর depend করে, object-এর equality lifecycle-এর মধ্যে change করতে পারে।

এটি ORM এবং hash-based collection use-এ subtle সমস্যা তৈরি করে।

Common strategies:

  • Application-generated stable ID
  • Immutable business key
  • Carefully designed persistence identity
  • Reference identity before persistence

এই topic advanced persistence design-এর অংশ।

Beginner level-এর key lesson:

Equality field stable হওয়া উচিত এবং object lifecycle বুঝে নির্বাচন করতে হবে।


String Comparison

Strings objects।

String content compare করতে:

firstString.equals(
        secondString
);

Avoid:

firstString
        == secondString

== references compare করে।

Example:

String first =
        new String("Java");

String second =
        new String("Java");

System.out.println(
        first == second
);

System.out.println(
        first.equals(second)
);

Output:

false
true

Null-Safe String Comparison

If variable may be null:

"Java".equals(
        courseTitle
);

এটি safe, কারণ literal null নয়।

Or:

Objects.equals(
        firstTitle,
        secondTitle
);

তবে required domain fields constructor-এ non-null রাখা stronger design।


What Is toString()?

Every Java object inherits toString() from Object

Default output সাধারণত এমন:

Course@5acf9800

এটি class name এবং hash-related representation-এর মতো দেখায়, কিন্তু business debugging-এর জন্য useful নয়।

toString() override করে meaningful representation দেওয়া যায়।


Overriding toString()

@Override
public String toString() {
    return "Course{"
            + "code='"
            + code
            + '\''
            + ", title='"
            + title
            + '\''
            + ", published="
            + published
            + '}';
}

Usage:

System.out.println(
        javaCourse
);

Java automatically toString() call করবে।

Possible output:

Course{code='JAVA', title='Java and OOP Foundation', published=false}

What Should toString() Include?

Useful fields:

  • Stable identity
  • Important state
  • Debugging-relevant information

Avoid including:

  • Password
  • Access token
  • Secret key
  • Full payment card information
  • Sensitive personal information
  • Very large collections
  • Recursive object graphs

Example unsafe:

return "User{"
        + "email='"
        + email
        + '\''
        + ", password='"
        + password
        + '\''
        + '}';

Logs-এ secrets leak হতে পারে।


toString() Is Not a Serialization Format

toString() debugging এবং human-readable representation-এর জন্য।

এটিকে depend করা উচিত নয়:

  • API response format হিসেবে
  • Database storage format হিসেবে
  • Stable machine-readable protocol হিসেবে
  • CSV বা JSON replacement হিসেবে

toString() implementation future-এ change হতে পারে।


Complete Course Example

Course.java

import java.util.Objects;

public class Course {

    private final String code;

    private String title;
    private boolean published;

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

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

        this.code =
                code.strip()
                        .toUpperCase();

        this.title =
                title.strip();

        this.published = false;
    }

    public boolean changeTitle(
            String newTitle
    ) {
        if (
                newTitle == null
                || newTitle.isBlank()
        ) {
            return false;
        }

        title =
                newTitle.strip();

        return true;
    }

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

        published = true;

        return true;
    }

    public String getCode() {
        return code;
    }

    public String getTitle() {
        return title;
    }

    public boolean isPublished() {
        return published;
    }

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

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

        Course course =
                (Course) other;

        return code.equals(
                course.code
        );
    }

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

    @Override
    public String toString() {
        return "Course{"
                + "code='"
                + code
                + '\''
                + ", title='"
                + title
                + '\''
                + ", published="
                + published
                + '}';
    }
}

Using Equality and toString()

Main.java

public class Main {

    public static void main(String[] args) {
        Course first =
                new Course(
                        "java",
                        "Java Foundation"
                );

        Course second =
                new Course(
                        "JAVA",
                        "Java and OOP Foundation"
                );

        Course third =
                first;

        System.out.println(
                first == second
        );

        System.out.println(
                first.equals(second)
        );

        System.out.println(
                first == third
        );

        first.publish();

        System.out.println(first);
        System.out.println(second);
    }
}

Output:

false
true
true
Course{code='JAVA', title='Java Foundation', published=true}
Course{code='JAVA', title='Java and OOP Foundation', published=false}

Interpretation:

first == second

false, কারণ separate objects।

first.equals(second)

true, কারণ code same এবং equality code-based।

first == third

true, কারণ same object reference।


A Subtle Design Observation

Previous example-এ two different objects same course identity represent করছে, কিন্তু titles এবং published states different।

Same identity
Different current state

এটি possible, especially when:

  • Different application sessions
  • Cached and fresh copies
  • Database entity loaded multiple times
  • Distributed services hold separate representations

Logical equality same entity identify করতে পারে, কিন্তু state synchronization automatically করে না।

Equal objects মানেই একই in-memory object নয়।


getClass() vs instanceof

equals()-এ two common type checks দেখা যায়।

getClass()
        != other.getClass()

অথবা:

!(other instanceof Course)

Inheritance-এর সঙ্গে equality design subtle।

getClass() exact same runtime class require করে।

instanceof subclasses allow করতে পারে, যা symmetry বা transitivity problems তৈরি করতে পারে।

এই module inheritance focus করছে না।

Beginner domain entities-এর জন্য exact-class comparison একটি clear starting point।


Common Mistakes

Using == for Logical Equality

Wrong:

if (firstCourse == secondCourse) {
}

এটি same object check করে, same course নয়।

Use:

firstCourse.equals(
        secondCourse
);

যদি logical equality implemented থাকে।


Comparing Strings with ==

Wrong:

title == "Java"

Use:

"Java".equals(title)

Calling a Method on null

Course course = null;

course.publish();

Result:

NullPointerException

Overriding equals() Without hashCode()

Hash-based collections inconsistent হতে পারে।


Including Mutable Fields in Equality

Title বা published state change হলে equality change হতে পারে।

Stable identity prefer করুন।


Using Every Field in Entity Equality

Entity-এর current state এবং identity এক জিনিস নয়।

সব fields compare করলে same entity-এর updated copy unequal হয়ে যেতে পারে।


Returning Secrets from toString()

Logs-এ sensitive data leak হতে পারে।


Treating toString() as JSON

toString() stable machine contract নয়।


Practice Exercises

Exercise 1: Trace Shared References

Predict করুন:

Course first =
        new Course(
                "JAVA",
                "Java Foundation"
        );

Course second =
        first;

second.changeTitle(
        "Modern Java"
);

System.out.println(
        first.getTitle()
);

Result explain করুন।


Exercise 2: Separate Objects

Create two separate Course objects with the same code।

Compare using:

==
equals()

Explain the different results।


Exercise 3: Implement Learner Equality

Create a Learner class with:

learnerId
name
email

Assume learnerId stable এবং unique।

Implement:

equals()
hashCode()
toString()

Do not include email in toString() if you consider it unnecessary personal data for logs।


Exercise 4: Fix String Comparison

Fix:

if (
        course.getCode()
        == "JAVA"
) {
}

Exercise 5: Null Safety

Rewrite safely:

course.publish();

when course may be null।

Then explain why preventing null earlier may be better।


Exercise 6: Equality Field Selection

Choose appropriate equality fields for:

  1. Course
  2. Money
  3. Enrollment
  4. EmailAddress

Explain whether each behaves more like an entity or value object।


Exercise 7: Safe toString()

Review:

@Override
public String toString() {
    return "User{"
            + "email='"
            + email
            + '\''
            + ", password='"
            + password
            + '\''
            + '}';
}

Identify the security problem and fix it।


Predict the Result

Question 1

Course first =
        new Course(
                "JAVA",
                "Java"
        );

Course second =
        first;

System.out.println(
        first == second
);

Question 2

Course first =
        new Course(
                "JAVA",
                "Java"
        );

Course second =
        new Course(
                "JAVA",
                "Modern Java"
        );

System.out.println(
        first == second
);

System.out.println(
        first.equals(second)
);

Assume equality code-based।


Question 3

String first =
        new String("Java");

String second =
        new String("Java");

System.out.println(
        first == second
);

System.out.println(
        first.equals(second)
);

Question 4

Course course = null;

System.out.println(
        course.getTitle()
);

Predict the Result Answers

Answer 1

true

Both references same object point করে।

Answer 2

false
true

References different, logical identity same।

Answer 3

false
true

== references compare করেছে। equals() String content compare করেছে।

Answer 4

Runtime-এ:

NullPointerException

Knowledge Check

Question 1

Object reference কী?

Question 2

Reference assignment কি object copy করে?

Question 3

Aliasing কী?

Question 4

Reference reassign করা এবং object mutate করার পার্থক্য কী?

Question 5

null কী represent করে?

Question 6

NullPointerException কখন হয়?

Question 7

Objects-এর ক্ষেত্রে == কী compare করে?

Question 8

equals() কী compare করতে পারে?

Question 9

equals() override করলে hashCode() কেন override করতে হয়?

Question 10

Equal objects কি same object হতে হবে?

Question 11

Mutable fields equality-তে risky কেন?

Question 12

toString()-এর purpose কী?

Question 13

toString()-এ sensitive data include করা উচিত নয় কেন?

Question 14

String content compare করতে == না equals() ব্যবহার করা উচিত?


Knowledge Check Answers

Answer 1

Object-এর location বা access path represent করা value, যা reference variable ধারণ করে।

Answer 2

না। এটি reference value copy করে।

Answer 3

Multiple references একই object point করলে।

Answer 4

Reference reassign করলে variable অন্য object point করে। Object mutate করলে referenced object-এর state change হয়।

Answer 5

Reference কোনো object point করছে না।

Answer 6

Null reference দিয়ে instance field বা method access করলে।

Answer 7

দুই references exact same object point করছে কি না।

Answer 8

Domain-defined logical identity বা value equality।

Answer 9

Equal objects-এর same hash code থাকা contract-এর requirement।

Answer 10

না। Separate objects logically equal হতে পারে।

Answer 11

Field change হলে object-এর equality এবং hash code change হতে পারে।

Answer 12

Human-readable debugging এবং logging representation দেওয়া।

Answer 13

Logs এবং error messages-এর মাধ্যমে secrets বা private information leak হতে পারে।

Answer 14

equals()


Lesson Summary

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

  • Object variable সাধারণত reference ধারণ করে
  • Reference assignment নতুন object তৈরি করে না
  • Multiple references same object point করতে পারে
  • Shared reference দিয়ে mutation সব references থেকে visible
  • Reference reassign করলে variable অন্য object point করে
  • Java object reference values by value pass করে
  • null object absence represent করে
  • Null reference access করলে NullPointerException হয়
  • Required values early validate করলে null handling কমে
  • == object reference identity compare করে
  • equals() logical equality define করতে পারে
  • Default equals() reference identity-based
  • Stable identity fields entity equality-এর জন্য useful
  • Mutable fields equality-তে risky
  • equals() contract reflexive, symmetric, transitive, consistent এবং non-null
  • equals() override করলে hashCode()-ও override করতে হয়
  • Equal objects same hash code দেয়
  • Objects.equals() null-safe comparison দেয়
  • String content equals() দিয়ে compare করতে হয়
  • toString() useful debugging representation দেয়
  • toString() sensitive data expose করা উচিত নয়
  • toString() serialization contract নয়
  • Equal objects একই in-memory object হওয়া বাধ্যতামূলক নয়
  • Equality strategy একটি domain design decision

Next Lesson

পরবর্তী lesson:

Composition and Object Relationships

আমরা শিখব:

  • One object referencing another object
  • has-a relationships
  • Association এবং composition
  • Learner, Course, এবং Enrollment আলাদা objects হিসেবে model করা
  • Duplicate state avoid করা
  • Object collaboration
  • Relationship ownership
  • Composition কেন inheritance-এর চেয়ে অনেক ক্ষেত্রে safer