Question #91EasyGeneralImportant

Types of principles in software engineering ?

Answer

Overview

Software engineering principles are guidelines that help write maintainable, scalable, and clean code. The most important ones are SOLID, DRY, KISS, YAGNI, and others.


1. SOLID Principles

S — Single Responsibility Principle

A class should have only one reason to change.

dart
// ❌ Bad — UserService does too much
class UserService {
  Future<User> fetchUser(int id) async { ... }
  void sendEmail(String email) { ... }       // Wrong place
  void saveToDatabase(User user) { ... }     // Wrong place
}

// ✅ Good — split responsibilities
class UserService { Future<User> fetchUser(int id) async { ... } }
class EmailService { void sendEmail(String email) { ... } }
class UserRepository { void save(User user) { ... } }

O — Open/Closed Principle

Open for extension, closed for modification.

dart
abstract class Shape { double area(); }
class Circle extends Shape {  double area() => 3.14 * r * r; }
class Rectangle extends Shape {  double area() => w * h; }
// Add new shapes without modifying existing code

L — Liskov Substitution Principle

Subclasses should be substitutable for their parent.

dart
class Animal { void makeSound() => print('...'); }
class Dog extends Animal {  void makeSound() => print('Woof'); }
void speak(Animal a) => a.makeSound(); // Works with Dog too

I — Interface Segregation Principle

Don't force clients to depend on interfaces they don't use.

dart
// ❌ Fat interface
abstract class Worker { void work(); void eat(); void sleep(); }

// ✅ Segregated
abstract class Workable { void work(); }
abstract class Eatable { void eat(); }
class HumanWorker implements Workable, Eatable { ... }
class RobotWorker implements Workable { void work() { ... } }

D — Dependency Inversion Principle

Depend on abstractions, not concretions.

dart
// ❌ Depends on concrete class
class OrderService { final SqlDatabase db = SqlDatabase(); }

// ✅ Depends on abstraction
abstract class Database { Future<void> save(Order order); }
class OrderService {
  final Database db; // Can be SQL, NoSQL, mock
  OrderService(this.db);
}

2. DRY — Don't Repeat Yourself

Extract repeated code into reusable functions/widgets.

dart
// ✅ Reusable
Widget primaryButton(String text, VoidCallback onTap) =>
    ElevatedButton(onPressed: onTap, child: Text(text));

3. KISS — Keep It Simple, Stupid

Write the simplest solution that works.


4. YAGNI — You Aren't Gonna Need It

Don't add functionality until it's actually needed.


5. Separation of Concerns

Each layer/module handles only its own responsibility (UI, Logic, Data).


Summary Table

PrincipleCore Idea
SOLIDObject-oriented design rules
DRYNo code duplication
KISSKeep code simple
YAGNIDon't over-engineer
SoCSeparate UI, logic, data
Law of DemeterTalk only to immediate friends