# Large ClassA intermediate-level guide to Large Class: before-and-after java code and diagrams for a CS student.

## The Swiss Army Knife Problem

Imagine you are in your kitchen and need to chop an onion. You reach for a knife, but instead of a simple blade, you pull out a heavy, oversized tool that includes a screwdriver, a spoon, a saw, and a bottle opener. It is bulky, difficult to grip, and because all these tools are attached to one handle, trying to use the saw might accidentally snap the spoon.

In software, we often fall into this same trap by creating "God Objects"—classes that try to do everything for everyone. You start with an `Order` class meant to track items, but soon you find yourself adding credit card details for payments and shipping addresses for logistics. When one class takes on too many roles, it becomes a Large Class.

```java
public class Order {
    private String orderId;
    private List<String> items;
    private double totalAmount;

    // Order management
    public void addItem(String item, double price) {
        items.add(item);
        totalAmount += price;
    }

    // Payment processing (Responsibility 2)
    private String cardNumber;
    private String expiryDate;
    public void processPayment() {
        System.out.println("Processing $" + totalAmount + " via card " + cardNumber);
    }

    // Shipping/Logistics (Responsibility 3)
    private String shippingAddress;
    private String carrierService;
    public void scheduleShipping() {
        System.out.println("Shipping to " + shippingAddress + " via " + carrierService);
    }
}
```

In the diagram below, notice how the `Order` class is forced to manage three entirely different domains: order tracking, payment data, and shipping logistics.

```mermaid
classDiagram
    class Order {
        -String orderId
        -List~String~ items
        -double totalAmount
        -String cardNumber
        -String expiryDate
        -String shippingAddress
        -String carrierService
        +addItem(String, double)
        +processPayment()
        +scheduleShipping()
    }
```

## Why Bloated Classes Hurt Your Code

A Large Class creates three specific types of friction:

1.  **High Cognitive Load**: As a developer, you can only hold so much information in your head at once. When a class has dozens of fields and methods, it becomes exhausting to understand how they all relate.
2.  **Fragility**: Because the `Order` class is holding everything, a change to the payment logic might accidentally break something in the shipping logic because they share the same memory space or variables. This violates the Single Responsibility Principle (SRP), which states that a class should have only one reason to change.
3.  **Testing Complexity**: To write a simple test for adding an item to an order, you might be forced to provide valid credit card numbers and shipping addresses just to get the object to initialize.

## From Bloat to Balance: Extract Class

To fix this, we use a refactoring technique called **Extract Class**. Instead of one class doing everything, we identify groups of data and behavior that belong together and move them into their own specialized classes. 

The goal is high "Cohesion"—a term meaning that the things inside a single class are closely related to one another. By moving payment details into a `PaymentInfo` class and shipping details into a `ShippingInfo` class, we achieve better cohesion.

```java
public class Order {
    private String orderId;
    private List<String> items;
    private double totalAmount;
    private PaymentInfo paymentInfo;
    private ShippingInfo shippingInfo;

    public Order(PaymentInfo payment, ShippingInfo shipping) {
        this.paymentInfo = payment;
        this.shippingInfo = shipping;
    }

    public void addItem(String item, double price) {
        items.add(item);
        totalAmount += price;
    }

    public void processPayment() {
        paymentInfo.process(totalAmount);
    }

    public void scheduleShipping() {
        shippingInfo.ship();
    }
}

class PaymentInfo {
    private String cardNumber;
    private String expiryDate;

    public PaymentInfo(String card, String expiry) {
        this.cardNumber = card;
        this.expiryDate = expiry;
    }

    public void process(double amount) {
        System.out.println("Processing $" + amount + " via card " + cardNumber);
    }
}

class ShippingInfo {
    private String address;
    private String carrierService;

    public ShippingInfo(String address, String carrier) {
        this.address = address;
        this.carrierService = carrier;
    }

    public void ship() {
        System.out.println("Shipping to " + address + " via " + carrierService);
    }
}
```

Now, the `Order` class no longer manages strings like `cardNumber`. Instead, it simply holds references to its specialized helpers. The runtime interaction changes from one giant object doing everything to a coordinated effort between smaller objects:

```mermaid
sequenceDiagram
    participant O as Order
    participant P as PaymentInfo
    participant S as ShippingInfo

    O ->> P: process(totalAmount)
    P -->> O: 
    O ->> S: ship()
    S -->> O: 
```

In this new structure, the `Order` class acts as a coordinator. It knows *when* to pay and *when* to ship, but it doesn't need to know the messy details of *how* a credit card is validated or *how* a carrier service operates.

## When to Use It, and When Not To

Extracting classes is highly effective when you notice "The And Problem." If you describe your class as "This class manages orders AND payments AND shipping," it is a clear candidate for refactoring.

However, do not be dogmatic about file length or line counts. Some classes are naturally large because they manage one very complex, singular process (like a complex state machine). Size itself isn't the enemy; too many unrelated responsibilities is what creates technical debt. If a class is 200 lines long but only does one specific thing with high precision, it is likely fine.

## Takeaways

- Identify Large Classes by looking for the word "and" in their descriptions.
- Use **Extract Class** to move related fields and methods into new, specialized objects.
- Aim for high cohesion: ensure each class has a single, focused responsibility.

## Usage

**Using the refactored Order class with specialized helper objects**

```java
PaymentInfo payment = new PaymentInfo("1234-5678", "12/25");
ShippingInfo shipping = new ShippingInfo("123 Java Lane", "FedEx");
Order order = new Order(payment, shipping);
order.addItem("Laptop", 1200.00);
order.processPayment();
```
