SOLID در Design Pattern چیست؟ - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

SOLID در Design Pattern چیست؟

+1 امتیاز
سلام . وقتی به شما میگن باید SOLID رو رعایت کنی در کد نویسی یعنی منظورشون چیه در ضمن من در حال کد زدن با C++ هستم.
سوال شده اردیبهشت 3, 1399  بوسیله ی AliStar (امتیاز 164)   2 20 32

3 پاسخ

+2 امتیاز

یکی از پایه ترین طراحی الگو هایی هست که هر برنامه نویسی باید رعایت کنه .SOLID در واقع سرنام 5 تا طراحی هستش.

1 - Single Responsibility Principle :

این اصل تاکید داره که هر کلاسی مسئولیت واحدی داشته باشه .اینطور نباشه که در طول عمر توسعه کد ، کلاس های متدی هایی داشته باشند که موضوعات بی ارتباط به مسئولیت اصلی کلاس را پیاده سازی کرده باشند . فرض کنید قرار یک کلاس دفترچه یادداشت بسازیم که هر بار بشه بهش خاطره اضافه کرد :

struct Journal
{
 string title;
 vector<string> entries;

explicit Journal(const string& title) : title{title} {}
 };

 void Journal::add(const string& entry)
 {
   static int count = 1;
    entries.push_back(boost::lexical_cast<string>(count++) + ": " + entry);
 }


int main(){
   Journal j{"Dear Diary"};
   j.add("I cried today");
   j.add("I ate a bug");

   return 0;
}

حالا فرض کنید قصد داریم داده های کلاس را ذخیره کنیم .به صورت زیر:

 void Journal::save(const string& filename)
 {
 ofstream ofs(filename);
 for (auto& s : entries)
 ofs << s << endl;
 }

این روش توسعه کد در آینده مساله ساز میشه کلاس دفترچه خاطرات وظیفه داشت خاطرات را نگه داره ولی اینگار الان وظیفه ذخیره سازی هم جز مسئولیت هایی جدیدش شده .حالا فرض کنیم چند وقت دیگه تصمیم بگیرن بجای ذخیره سازی بر روی حافظه این اطلاعات در cloud ذخیره شه دوباره یک متد دیگه هر بار این کلاس باید بر مسئولیت هایی که مربوط به خودش نیست تست بشه . ما این مشکل را به صورت زیر رفع می کنیم.

 struct PersistenceManager
 {
    static void save(const Journal& j, const string& filename)
     {
         ofstream ofs(filename);
         for (auto& s : j.entries)
             ofs << s << endl;
      }
 };

یک آنتی پترن رایج در این Good Object هستش که افراد به اشتباه کلاس هایی ایجاد می کنند که همه کاری این کلاس انجام میده فقط آب سرد کن نداره که همانطور دیدم از نوشتن این نوع کلاس ها باید خودداری کنید و یا اینکه اگر همچین چیزی دارید هر چه زودتر refactor کنید مجموعه IDE های شرکت JetBrain ازجمله CLion که برای C++ هستش ابزاری خوبی برای refactor این نوع کلاس ها داره.

 

 

پاسخ داده شده اردیبهشت 3, 1399 بوسیله ی toopak (امتیاز 2,458)   16 48 66
ویرایش شده اردیبهشت 4, 1399 بوسیله ی toopak
+1 امتیاز

درود؛ اصول SOLID از اصول Clean Code در برنامه‌نویسی هست، که به پنج امر اشاره داره:

  1. Single responsibility principle
  2. Open closed principle
  3. Liskiv subsitution principle
  4. Interface segration principle
  5. Dependency inversion principle

که شما برای داشتند ساختار هرچه بهتر مستلزم به رعایت این اصول هستید (هرچند که برنامه‌نویس‌ها اعتقادی بهش ندارند cool) . برای توضیحات کامل‌تر می‌توانید از کتاب آقای رابرت ماتین به اسم Clean Code و کتاب Clean Arch استفاده کنید که به خوبی توضیحات لازم را داده‌اند.

پاسخ داده شده اردیبهشت 4, 1399 بوسیله ی mg_ramezani (امتیاز 727)   1 1 12
نمی دونم حالا شما بهش اعتقاد دارید یا نه ولی بعد از یک مدت رعایت کردن واقعاً طراحی کلاس ها خیلی روان تر و تمیز تر انجام میشه.
درود؛ بله اون متن داخل پرانتز را صرفاً برای مزاح نوشتم.
+3 امتیاز

2 -Open-Closed Principle :

اصل بعدی اشاره داره به این موضوع که کدی نوشته شده به گونه ی باشه که  نسبت به توسعه باز باشه ولی نسبت به تغیرات بسته باشه این یعنی چی؟ به مثال زیر توجه کنید در این مثال ما قصد داریم یک سری محصولات را براساس رنگشون  فیلتر کنیم.

enum class Color { Red, Green, Blue };
enum class Size { Small, Medium, Large };

 struct Product
 {
 string name;
 Color color;
 Size size;
 };

 struct ProductFilter
 {
    typedef vector<Product*> Items;
 };

 ProductFilter::Items ProductFilter::by_color(Items items,Color color)
 {
    Items result;
    for (auto& i : items)
    if (i->color == color)
       result.push_back(i);
     return result;
 }

فرض کنید مجددا از شما خواسته میشه که فیلتر اندازه را هم به کدتان اضافه کنید.

 ProductFilter::Items ProductFilter::by_size(Items items,Size size)
 {
   Items result;
   for (auto& i : items)
   if (i->size == size)
     result.push_back(i);
    return result;
 }

فرض مجدداً از شما درخواست میشه که هم نسبت به رنگ و اندازه با هم فیلتر کنید.

 ProductFilter::Items ProductFilter::by_color_and_size(Items items, Size size, Color color)
 {
    Items result;
    for (auto& i : items)
    if (i->size == size && i->color == color)
       result.push_back(i);
    return result;
 }

اگر دقت کنید OCP اینجا نقض شده در صورتیکه ما قصد داریم هر بار فیلتر جدید اضافه کنیم در صورتیکه داریم کل یونیت مربوط به فیلتر را تغییر میدم ساختار کد با در این مرحله به گونه ای تغییر کنه که اضافه کردن فیلتر جدید باعث توسعه کد بشه و هیچ جای دیگر کد جز خودش تغییر نکنه . به کد تغییر یافته در زیز دقت کنید:

//Test.h

#pragma once
#include  <string>
#include  <vector>
#include  <iostream>

using namespace std;

enum  class Color { Red, Green, Blue };
enum class Size { Small, Medium, Large };

struct Product
{
	std::string name_;
	Color color_;
	Size size_;

};

using ProductP = Product *;
using ProductPVec = std::vector<ProductP>;

template<typename T>
struct AndSpec;


template<typename T>
struct Spec
{
	virtual  bool is_satisfy(T* value) = 0;
	AndSpec<T> operator&&(T& value)
	{
		return AndSpec<T>(*this, value);
	}

};

struct ColorSpec : public Spec<Product>
{

	Color color_;
	ColorSpec(Color color) :
		color_(color) {}

	bool is_satisfy(Product* value) override
	{
		return value->color_ == color_;
	}
};

struct SizeSpec : public Spec<Product>
{

	Size size_;
	SizeSpec(Size size) :
		size_(size) {}

	bool is_satisfy(Product* value) override
	{
		return value->size_ == size_;
	}
};


template <typename  T>
struct AndSpec :  Spec<T>
{
	Spec<T>& first_;
	Spec<T>& second_;

	AndSpec(Spec<T>& first, Spec<T>& second) :
		first_(first),
		second_(second)
	{

	}
	bool is_satisfy(T* value) override
	{
		return first_.is_satisfy(value) && second_.is_satisfy(value);
	}


};



template<typename  T>
struct Filter
{
	ProductPVec filter(ProductPVec items,Spec<T>& spec)
	{
		ProductPVec result;
		for (auto& item : items)
			if (spec.is_satisfy(item))
				result.push_back(item);
		
		return result;
	}
};


void print(Product* value);

void printAll(ProductPVec items);

 

//Test.cpp
#include "Test.h"



void print(Product* value)
{
	cout << "name:" << value->name_ << endl;
}

void printAll(ProductPVec items)
{
	for (auto& item : items)
		print(item);

}

 

//main.cpp


#include  "Test.h"

int main()
{
	Product apple{ "Apple", Color::Green, Size::Small };
	Product tree{ "Tree", Color::Green, Size::Large };
	Product house{ "House", Color::Blue, Size::Large };
	ProductPVec all{ &apple,&tree,&house };

	auto green = ColorSpec(Color::Green);
	auto large = SizeSpec(Size::Large);
	
	auto spc = AndSpec<Product>(green,large);
	Filter<Product> fp;
        auto filtered = fp.filter(all, spc);
	
	printAll(filtered);
	

}

 

پاسخ داده شده اردیبهشت 4, 1399 بوسیله ی toopak (امتیاز 2,458)   16 48 66
ویرایش شده اردیبهشت 4, 1399 بوسیله ی toopak
...