Principle:
Pattern:
"Every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class."
class User
{
int ID;
string Username;
string Email;
string PasswordHash;
static User get(id)
{
return [user from DB];
}
}
var user = User::get(123);
class User
{
int ID;
string Username;
string Email;
string PasswordHash;
}
class UserRepository
{
static User get(id)
{
return [user from DB];
}
}
var user = UserRepository::get(123);
"Software entities should be open for extension, but closed for modification."
class Animal
{
int LegCount()
{
return 4;
}
}
class Human : Animal
{
int LegCount()
{
return 2;
}
}
interface Animal
{
int LegCount();
}
class Human : Animal
{
int LegCount()
{
return 2;
}
}
abstract class FourLeggedAnimal : Animal
{
int LegCount()
{
return 4;
}
}
"if S is a subtype of T, then objects of type T may be replaced with objects of type S without altering correctness."
abstract class Vehicle
{
void StartEngine() { ... }
...
}
class Car : Vehicle { ... }
void GoSomewhere(Vehicle vehicle)
{
vehicle.StartEngine();
...
}
class Bicycle : Vehicle { ... }
abstract class Vehicle
{
...
}
abstract class MotorVehicle : Vehicle
{
void StartEngine() { ... }
}
class Car : MotorVehicle { ... }
class Bicycle : Vehicle { ... }
void GoSomewhere(Vehicle vehicle)
{
if (vehicle is MotorVehicle mv)
mv.StartEngine();
...
}
"No client should be forced to depend on methods it does not use."
interface UserRepository
{
User get(id);
void save(user);
}
class UserServiceClient : UserRepository
{
User get(id)
{
return [user from microservice];
}
void save(user)
{
[???]
}
}
interface UserReader
{
User get(id);
}
class UserServiceReader : UserReader
{
User get(id)
{
return [user from microservice];
}
}
interface UserWriter
{
void save(user);
}
interface UserRepository : UserReader,
UserWriter
"High-level modules should not depend on low-level modules. Both should depend on abstractions."
"Abstractions should not depend on details. Details should depend on abstractions.
class UserRepository
{
DB db;
new()
{
db = new DB(Global.ConnString);
}
User get(id)
{
return [user from db];
}
}
var user_repo = new UserRepository();
var user = user_repo.get(123);
class UserRepository
{
DB db;
new(DB injected_db)
{
db = injected_db;
}
User get(id)
{
return [user from db];
}
}
var db = new DB(Global.ConnString);
var user_repo = new UserRepository(db);
var user = user_repo.get(123);
"The process of restructuring existing computer code without changing its external behavior."