심플 솔리드
목차
1. 단일 책임 원칙
There should never be more than one reason for a class to change.
위반
/* This class has two reasons to change: it's properties and storing data in the database */
public class Customer {
public string Name {get;set}
public string LastName {get;set}
public string Email {get;set}
private readonly string _repository;
public Customer(string repository, string name, string lastName, string email) {
_repository = repository;
Name = name;
LastName = lastName;
Email = email;
}
public void Save() {
if(_repository == "SQLServer") {
/* Saving in SQLServer*/
}
else if(_repository == "MongoDB") {
/* Saving in MongoDB*/
}
else{
throw new Exception("Database not supported");
}
}
}
규정 준수
/* This class now cares only about it's properties*/
public class Customer {
public string Name {get;set}
public string LastName {get;set}
public string Email {get;set}
public Customer(string name, string lastName, string email) {
Name = name;
LastName = lastName;
Email = email;
}
}
/* this class only cares about storing data in the database*/
public class CustomerRepository {
private readonly string _repository;
public CustomerRepository(string repository){
_repository = repository;
}
public void Save(Customer customer){
if(_repository == "SQLServer"){
/* Saving in SQLServer*/
}
else if(_repository == "MongoDB"){
/* Saving in MongoDB*/
}
else{
throw new Exception("Database not supported");
}
}
}
2. 개방-폐쇄 원칙
Software entities (classes, modules, functions, etc.)
should be open for extension, but closed for
modification.
위반
public class EmailNotifier {
public void Notify(string message){
/* Notify via e-mail */
}
}
public class SMSNotifier {
public void Notify(string message){
/* Notify via SMS */
}
}
public class AlertManager {
public void SendNotification(List<string> notifiers, string message){
/* WARNING: New notifiers cannot be added without modifying this module */
foreach(var notifier in notifiers){
switch(notifier){
case "Email":
var email = new EmailNotifier();
email.Notify(message);
case "SMS":
var sms = new SMSNotifier();
sms.Notify(message);
}
}
}
}
규정 준수
public class Notifier {
public void Notify(string message){
return;
}
}
public class EmailNotifier : Notifier {
public void Notify(string message){
/* Notify via e-mail */
}
}
public class SMSNotifier : Notifier {
public void Notify(string message){
/* Notify via SMS */
}
}
public class WhatsAppNotifier : Notifier {
public void Notify(string message){
/* Notify via WhatsApp */
}
}
public class AlertManager {
public void SendNotification(List<Notifier> notifiers, string message){
/* New notifiers can be added without modifying this module */
foreach(var notifier in notifiers){
notifier.Notify(message);
}
}
}
3. Liskov 치환 원리
Functions that use pointers or references to base
classes must be able to use objects of derived classes
without knowing it.
위반
public interface IDatabaseRepository {
bool Connect(string connectionString);
Table GetTable(string tableName);
}
public class OracleRepository : IDatabaseRepository{
public bool Connect(string connectionString){
/* Connect to the database */
}
public Table GetTable(string tableName){
/* fetch table and return it*/
}
}
public class SQLServerRepository : IDatabaseRepository{
public bool Connect(string connectionString){
/* Connect to the database */
}
public Table GetTable(string tableName){
/* fetch table and return it*/
}
}
/* Imagine MongoDB support was added later in the application: */
public class MongoDBRepository : IDatabaseRepository {
public bool Connect(string connectionString){
/* Connect to the database */
}
public Table GetTable(string tableName){
/* MongoDB does not have Tables!! */
throw new NotImplementedException();
}
}
public class Client {
public void GetTable(IDatabaseRepository repository, string tableName){
/* WARNING: If the MongoDBRepository object is passed as a parameter, calling GetTable() will break the application.
And we cannot check here if the type is either OracleRepository or SQLServerRepository because that would violate the Open-Closed Principle */
repository.GetTable(tableName);
}
}
규정 준수
public interface IDatabaseRepository {
bool Connect(string connectionString);
}
public interface IRelationalDatabaseRepository : IDatabaseRepository {
Table GetTable(string connectionString);
}
public class OracleRepository : IRelationalDatabaseRepository{
public bool Connect(string connectionString){
/* Connect to the database */
}
public Table GetTable(string tableName){
/* fetch table and return it*/
}
}
public class SQLServerRepository : IRelationalDatabaseRepository{
public bool Connect(string connectionString){
/* Connect to the database */
}
public Table GetTable(string tableName){
/* fetch table and return it*/
}
}
public class MongoDBRepository : IDatabaseRepository {
public bool Connect(string connectionString){
/* Connect to the database */
}
}
public class Client {
public void GetTable(IRelationalDatabaseRepository repository, string tableName){
/* Now we are safe from exceptions, because every instance of IRelationalDatabaseRepository must handle the GetData method.*/
repository.GetTable(tableName);
}
}
4. 인터페이스 분리 원칙
clients should not be forced to depend upon interfaces
that they do not use.
위반
public interface IDatabaseRepository {
Table GetTable(string tableName);
/* Imagine MongoDB support was added later in the application: */
Collection GetCollection(string collectionName);
}
public class SQLServerRepository : IDatabaseRepository {
public Table GetTable(string tableName) {
/* fetch table and return it*/
}
public Collection GetCollection(string collectionName) {
/*
Method GetCollection is being forced on this class.
SQLServer does not have Collections!
*/
throw new NotImplementedException();
}
}
/* Imagine MongoDB support was added later in the application: */
public class MongoDBRepository : IDatabaseRepository {
public Table GetTable(string tableName) {
/*
Method GetTable is being forced on this class.
MongoDB does not have Tables!
*/
throw new NotImplementedException();
}
public Collection GetCollection(string collectionName) {
/* fetch collection and return it*/
}
}
규정 준수
/* Split the IDatabaseRepository interface between IRelationalDatabaseRepository and INonRelationalDatabaseRepository so no implementation is forced to handle methods it doesn't need.*/
public interface IDatabaseRepository {
}
public interface IRelationalDatabaseRepository : IDatabaseRepository {
Table GetTable(string tableName);
}
public interface INonRelationalDatabaseRepository : IDatabaseRepository {
Collection GetCollection(string collectionName);
}
public class SQLServerRepository : IRelationalDatabaseRepository {
public Table GetTable(string tableName) {
/* fetch table and return it*/
}
}
public class MongoDBRepository : INonRelationalDatabaseRepository{
public Collection GetCollection(string collectionName) {
/* fetch collection and return it*/
}
}
5. 의존성 반전 원리
a. high level modules should not depend upon low
level modules. both should depend upon abstractions.b. abstractions should not depend upon details. details
should depend upon abstractions.
위반
public class CustomerRepository {
private readonly string _repository;
public CustomerRepository(string repository){
_repository = repository;
}
public void Save(Customer customer){
/* WARNING: The high level module CustomerRepository DEPENDS on the low level modules SQLServerRepository */
if(_repository == "SQLServer"){
var repository = new SQLServerRepository();
/* Saving in SQLServer*/
}
else{
throw new Exception("Database not supported");
}
}
}
규정 준수
public interface IDatabaseRepository{
void Save(Customer customer);
}
public class SQLServerRepository : IDatabaseRepository {
public void Save(Customer customer){
/* Saving in SQLServer*/
}
}
public class CustomerRepository {
private readonly IDatabaseRepository _repository;
public CustomerRepository(IDatabaseRepository repository){
_repository = repository;
}
/* Now the high level module CustomerRepository and the low level modules SQLServerRepository and MongoDBRepository DEPEND on the abstraction IDatabaseRepository */
public void Save(Customer customer){
_repository.Save(customer);
}
}
Reference
이 문제에 관하여(심플 솔리드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/veglos/simple-solid-195i텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)