Skip to content

Instantly share code, notes, and snippets.

@LeBaleiro
Last active September 3, 2023 22:04
Show Gist options
  • Save LeBaleiro/db33b91e8d9cf3c2510108ac188c4298 to your computer and use it in GitHub Desktop.
Save LeBaleiro/db33b91e8d9cf3c2510108ac188c4298 to your computer and use it in GitHub Desktop.
Open Closed Principle

This is an example of the open closed principle. The first file (2.non_ocp.dart) shows an example not using the principle and the second (3.using_ocp.dart) shows a refactor of it using the principle.

// ---------------------------------------------------------------------
// example NOT using the Open-Closed Principle:
class Shape {
Shape(this.type, this.value, this.height);
final String type;
final double value;
final double? height;
}
class AreaCalculator {
double calculateArea(Shape shape) {
if (shape.type == 'circle') {
// in this case the value is the radius
return pi * shape.value * shape.value;
} else if (shape.type == 'square') {
// in this case the value is the side of the square
return shape.value * shape.value;
} else if (shape.type == 'triangle') {
// in this case the value is the base of the triangle
return shape.value * shape.height! / 2;
} else {
return 0;
}
}
}
// ---------------------------------------------------------------------
// example USING the Open-Closed Principle:
abstract class Shape {
double calculateArea();
}
class Circle implements Shape {
Circle(this.radius);
final double radius;
@override
double calculateArea() {
return pi * radius * radius;
}
}
class Square implements Shape {
Square(this.side);
final double side;
@override
double calculateArea() {
return side * side;
}
}
class Triangle implements Shape {
Triangle(this.base, this.height);
final double base;
final double height;
@override
double calculateArea() {
return base * height / 2;
}
}
class AreaCalculator {
double calculateArea(Shape shape) {
return shape.calculateArea();
}
}
@MOPineyro
Copy link

Using switch patterns:

sealed class Shape {}

class Circle implements Shape {
  Circle(this.radius);
  final double radius;
}

class Square implements Shape {
  Square(this.side);
  final double side;
}

class Triangle implements Shape {
  Triangle(this.base, this.height);
  final double base;
  final double height;

}

double calculateArea(Shape shape) => switch (shape) {
  Square(length: var l) => l * l,
  Circle(radius: var r) => math.pi * r * r,
  Triangle(base: var b, height: var h) => (b * h) / 2,
};

@LeBaleiro
Copy link
Author

LeBaleiro commented Aug 29, 2023

@MOPineyro
good observation! The way switch works now in Dart can be helpful, it's a good approach too. But, in this case, it would break the open-closed principle, considering that for OCP we shouldn't be applying changes to the existing code by adding new statements. the principle states that we should prioritize the extension rather than the modification of the classes we already have in the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment