0% found this document useful (0 votes)
2 views15 pages

Chapter 05 - Objects and Data Structures

Chapter 5 of 'Clean Code' discusses the importance of data abstraction in software design, emphasizing the distinction between anemic classes (data structures with no methods) and domain classes (which encapsulate business logic). It highlights the advantages of object-oriented code over procedural code, particularly in terms of maintaining and extending functionality. The chapter also introduces the Law of Demeter, advocating for limited knowledge between classes to reduce dependencies and improve code maintainability.

Uploaded by

mmahdifarrokhy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views15 pages

Chapter 05 - Objects and Data Structures

Chapter 5 of 'Clean Code' discusses the importance of data abstraction in software design, emphasizing the distinction between anemic classes (data structures with no methods) and domain classes (which encapsulate business logic). It highlights the advantages of object-oriented code over procedural code, particularly in terms of maintaining and extending functionality. The chapter also introduces the Law of Demeter, advocating for limited knowledge between classes to reduce dependencies and improve code maintainability.

Uploaded by

mmahdifarrokhy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

Mohammadmahdi Farrokhy

Clean Code:

A Handbook of
Agile Software Craftsmanship

Chapter 05: Objects And Data Structures


Data abstraction

True abstraction hides data types and applies operations on them as public methods.

// BAD CODE: Reveals details of private fields // GOOD CODE: Uses private fields for a public behavior
public interface Vehicle { public interface Vehicle {
double getFuelTankCapacityInGallons(); double getPercentFuelRemaining();
double getGallonsOfGasoline(); }
}
Object/Data Anti-Symmetry

Anemic Classes: Data structures that contain data, but no methods. They're used only to
move data between classes and layers. That's why we call them Data Transfer Object(DTO).

Domain Classes: Hide data through abstraction, offering methods that implement Business
logics and define software behavior.
Procedural Code

In the code below, there are three anemic classes and a client class that uses them. Adding a
new business logic or new data structures affects only the client.
public class Square { public class Geometry {
public Point topLeft; public final double PI = 3.141592653589793;
public double side;
} public double area(Shape shape) throws NoSuchShapeException {
if (shape instanceof Square) {
public class Rectangle { Square s = (Square) shape;
public Point topLeft; return s.side * s.side;
public double height; } else if (shape instanceof Rectangle) {
public double width; Rectangle r = (Rectangle) shape;
} return r.height * r.width;
} else if (shape instanceof Circle) {
public class Circle { Circle c = (Circle) shape;
public Point center; return PI * c.radius * c.radius;
public double radius; }
}
throw new NoSuchShapeException();
}
}
Object-Oriented Code

Here is an Object-Oriented code with interfaces that define business rules. Adding a new
business logic means defining a new abstract method in the interface and implementing it in
concrete classes. So, adding new business logic affects all of them. Adding a new concrete
class affects the client class.
Object-Oriented Code

public interface Shape { public class Rectangle implements Shape { public class Circle implements Shape {
public double area(); public Point topLeft; public final double PI = 3.141592653589793;
} public double height; public Point center;
public double width; public double radius;
public class Square implements Shape {
public Point topLeft; @Override @Override
public double side; public double area() { public double area() {
return height * width; return PI * radius * radius;
@Override } }
public double area() { } }
return side * side;
}
}
Object-Oriented Code

public class ShapeService { public enum ShapeType { public class ShapeServiceFactory {


Shape shape; Rectangle, private ShapeServiceFactory() {
Circle, }
public ShapeService(Shape shape){ Square
this.shape = shape; } public static ShapeService createShapeService(ShapeType shapeType) {
Shape shape;
}
switch (shapeType) {
public static double calculateArea() { case ShapeType.Square:
return shape.area(); shape = new Square();
} break;
}
case ShapeType.Rectangle:
shape = new Rectangle();
break;

case ShapeType.Circle:
shape = new Circle();
break;
}

return new ShapeService(shape);


}
}
Object-Oriented Code

public class ClientClass {


private ShapeType shapeType;
private ShapeService shapeService;

public ClientClass(ShapeType shapeType) {


this.shapeType = shapeType;
this.shapeService = ShapeServiceFactory.createShapeService(shapeType);
}

public double calculateArea() {


return shapeService.calculateArea();
}
}
Procedural Form vs. Object-Oriented Form

Which approach to use for coding?


− Procedural code:
• Adding new data structures requires modification of all methods in client class.
• Suitable for systems likely to see more future behaviors and business logics.

− Object-Oriented Code:
• Adding new methods(business rules) demands modification of all concrete classes.
• Suitable for systems likely to introduce new data structures.
The Law Of Demeter

This law is stated in different was:


– A unit should have limited knowledge about others.
– Only units next to the current unit should be familiar with its details.
– Each unit should only talk to its neighbors.
– Don't talk to strangers.
The Law Of Demeter

Simply put, Law of Demeter states that method m() in class C should only be able to call
methods from:
• Class C
• An object from return type of method m()
• Parameters of method m()
• A field object of class C
This implies that sequential getter methods violate this principle.
The Law Of Demeter – BAD CODE

public class Airport { public class Flight { public class Client {


private AirportCode code; private Airport originAirport; private void operation() {
private Coordinate coordinate; private Airport destinationAirport; Order order = new Order();
private Location location; String originAirportName = order.getFlight().getOriginAirport().getName();
private String name; public Airport getOriginAirport() { }
return originAirport; }
public AirportCode getCode() { }
return code;
} public Airport getDestinationAirport() {
return destinationAirport;
public Coordinate getCoordinate() { }
return coordinate; }
}
public class Order {
public Location getLocation() { private Flight flight;
return location;
} public Flight getFlight() {
return flight;
public String getName() { }
return name; }
}
}
The Law Of Demeter – GOOD CODE

public class Airport { public class Flight { public class Order {


private AirportCode code; private Airport originAirport; private Flight flight;
private Coordinate coordinate; private Airport destinationAirport;
private Location location; public Flight getFlight() {
private String name; public Airport getOriginAirport() { return flight;
return originAirport; }
public AirportCode getCode() { }
return code; public String getOriginAirportName() {
} public Airport getDestinationAirport() { return flight.getOriginAirportName();
return destinationAirport; }
public Coordinate getCoordinate() { } }
return coordinate;
} public String getOriginAirportName() {
return originAirport.getName(); public class Client {
public Location getLocation() { } private void operation() {
return location; } Order order = new Order();
} String originAirportName = order.getOriginAirportName();
}
public String getName() { }
return name;
}
}
Data Transfer Object - DTO

Data structures are defined as classes with private variables and no methods. These
structures facilitate the transfer of data between different system layers. For instance, we
extract data from a database, place it into a DTO, and transmit it to other layers such as
domain or application. Consider simulating a flight with two classes: Flight, contains logic
methods and FlightDTO that only moves data. Our goal is to distinctly separate business
classes from data classes.
In brief we could say:

When we refer to data structures, we mean anemic classes with only getters and setters.
These classes store and move data, and are also recognized as DTOs. On the other side,
domain classes execute business logic and lack setter methods. We can only access their
data without changing it.

You might also like