كتابة التكرار بواسطة SOLID

في هذا المنشور سوف نتطرق إلى إجراءات الكتابة والمخفض. للبدء ، فكر في "تدفق" نموذجي ، ننفذ فيه العمليات التالية (علاوة على ذلك ، نعيد صياغة كل شيء حتى يتوافق رمزنا مع مبادئ SOLID).

1. إنشاء ملف مع الثوابت (هنا نحفظ أسماء أنواع الإجراءات)

export const REQUEST_DATA_PENDING = "REQUEST_DATA_PENDING"; export const REQUEST_DATA_SUCCESS = "REQUEST_DATA_SUCCESS"; export const REQUEST_DATA_FAILED = "REQUEST_DATA_FAILED"; export const PROFILES_PER_PAGE = "PROFILES_PER_PAGE"; export const CURRENT_PAGE = "CURRENT_PAGE"; 

2. قم بإنشاء ملف حيث نصف الإجراءات (هنا نقوم بتقديم طلب لحسابات المستخدمين والصفحات). أيضًا في المثال تم استخدام redux-thunk (كذلك سنرفض تبعيات مماثلة):

 export const requestBigDataAction = () => (dispatch) => { fetchingData(dispatch, BIG_DATA_URL, 50); } export const changeCurrentPAGE = (page) => ({ type: CURRENT_PAGE, payload: page }) function fetchingData(dispatch, url, profilesPerPage) { dispatch({type: REQUEST_DATA_PENDING}); fetch(url) .then((res) => { if(res.status !== 200) { throw new Error (res.status); } else { return res.json(); } }) .then((data) => {dispatch({type: REQUEST_DATA_SUCCESS, payload: data})}) .then(() => dispatch({type: PROFILES_PER_PAGE, payload: profilesPerPage})) .catch((err) => dispatch({type: REQUEST_DATA_FAILED, payload: ` . ${err.message}`})); } 

3. نكتب المخفض

 import { REQUEST_DATA_PENDING, REQUEST_DATA_SUCCESS, REQUEST_DATA_FAILED, PROFILES_PER_PAGE, CURRENT_PAGE } from '../constants/constants'; const initialState = { isPending: false, buffer: [], data: [], error: "", page: 0, profilesPerPage: 0, detailedProfile: {} } export const MainReducer = (state = initialState, action = {}) => { switch(action.type) { case REQUEST_DATA_PENDING: return Object.assign({}, state, {isPending: true}); case REQUEST_DATA_SUCCESS: return Object.assign({}, state, {page : 0, isPending: false, data: action.payload, error: "", detailedProfile: {}, buffer: action.payload}); case REQUEST_DATA_FAILED: return Object.assign({}, initialState, {error: action.payload}); case PROFILES_PER_PAGE: return Object.assign({}, state, {profilesPerPage: action.payload}); case CURRENT_PAGE: return Object.assign({}, state, {page: action.payload}); default: return state; } } 

4. تكوين المتجر (استخدام الوسيطة thunkMiddleware)

 import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import {createStore, applyMiddleware} from 'redux'; import {Provider} from 'react-redux'; import thunkMiddleware from 'redux-thunk'; import {MainReducer} from './reducers/mainReducer'; const store = createStore(MainReducer, applyMiddleware(thunkMiddleware)); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root')); 


5. قم بتوصيل المكون لإعادة
 const mapDispatchToProps = (dispatch)=>{ return { onRequestBigData: (event) =>{ dispatch(requestBigDataAction()); } } }; 

ربط أزرار ترقيم الصفحات لإعادة

 const mapDispatchToProps = (dispatch)=>{ return { onChangePage: (page) =>{ dispatch(changeCurrentPAGE(page)); } } }; 

المشكلة: المخفض الخاص بنا عبارة عن بيان تبديل كبير ، لذلك ، عند إضافة إجراء جديد ، أو تغيير سلوكه ، نحتاج إلى تغيير المخفض الخاص بنا ، الذي ينتهك مبادئ SOlid (مبدأ المسؤولية الفردية ومبدأ الانفتاح / التقارب).

الحل: سوف يساعدنا تعدد الأشكال. أضف إلى كل إجراء طريقة التنفيذ التي ستطبق التحديث وتعيد الحالة المحدثة. ثم سوف تأخذ المخفض لدينا النموذج

 export const MainReducer = (state = initialState, action) => { if(typeof action.execute === 'function') return action.execute(state); return state; }; 

الآن عند إضافة إجراء جديد ، لا نحتاج إلى تغيير المخفض ، ولا يتحول إلى وحش ضخم.

بعد ذلك ، التخلي عن thux-redux وإعادة كتابة الإجراءات

 import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import {createStore} from 'redux'; import {Provider} from 'react-redux'; // import thunkMiddleware from 'redux-thunk'; import {MainReducer} from './reducers/mainReducer'; const store = createStore(MainReducer); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root')); 

انتقل إلى المكون المتصل ، الذي يكون إجراءه غير متزامن (يجب تصحيحه قليلاً)

 const mapDispatchToProps = (dispatch)=>{ return { onRequestBigData: (event) =>{ requestBigDataAction(dispatch); }, } }; 

والانتقال إلى الإجراءات نفسها وإضافة طريقة التنفيذ إليها

 const type = 'bla-bla'; const requestDataPending = {execute: state => ({...state, isPending: true}), type}; const requestDataSuccess = payload => ({ execute: function (state) { return ({...state, page : 0, isPending: false, data: payload, error: "", detailedProfile: {}, buffer: payload}) }, type}) const profilesPerPageAction = profilesPerPage => ({ execute: state => ({...state, profilesPerPage: profilesPerPage}), type }); const requestDataFailed = errMsg => state => ({...state, error: ` . ${errMsg}`}); function fetchingData(dispatch, url, profilesPerPage) { dispatch(requestDataPending); fetch(url) .then((res) => { if(res.status !== 200) { throw new Error (res.status); } else { return res.json(); } }) .then((data) => {dispatch(requestDataSuccess(data))}) .then(() => dispatch(profilesPerPageAction(profilesPerPage))) .catch((err) => dispatch(requestDataFailed(err.message))); } export const requestBigDataAction = (dispatch) => { fetchingData(dispatch, BIG_DATA_URL, 50); } export const changeCurrentPAGE = page => ({ type, execute: state => ({...state, page}) }) 

ملاحظة: خاصية الكتابة مطلوبة (إذا لم تقم بإضافتها ، فسيتم طرح استثناء). ولكن بالنسبة لنا لا يهم على الإطلاق. لهذا السبب لم نعد بحاجة إلى ملف منفصل يسرد أنواع الإجراءات.

ملاحظة: في هذه المقالة ، طبقنا مبادئ SRP و OCP ، تعدد الأشكال ، تخلينا عن مكتبة الطرف الثالث وجعلنا كودنا أكثر نظافة ويمكن صيانته.

Source: https://habr.com/ru/post/ar475194/


All Articles