ابزارهای لازم برنامه نویسها
خبرنامه Frontend Focus
کتابخانه jQuery.mmenu
Domain-Driven Refactoring - Jimmy Bogard - NDC London 2022
Books, workshops, storming and more, all build up an idealized domain model. All describe great techniques for domain-driven greenfield applications. But what about the code we have? How can we take what's already built, and move it towards a better, more cohesive design?
In this session, we'll look at anemic, procedural, boring code and examine code smells that can point us in the right direction. We'll also look at standard design patterns for more complex behaviors and models, and how to recognize when (and when not) to apply them. Finally, we'll cover how to safely apply refactoring techniques to achieve our domain-driven model nirvana.
سری ویدیوهای NET Conf 2023.
.NET Conf 2023
.NET Conf 2023 is the largest .NET event hosted online! Co-organized by the .NET community and Microsoft and backed by the support of the .NET Foundation and ecosystem partners, it's your ticket to learning and finding inspiration for your upcoming software projects. Dive into the world of web, mobile, cloud, desktop, gaming, IoT, AI, and beyond, all powered by .NET. Whether you're just starting your coding journey or you're a seasoned pro, these sessions are tailored for everyone. Be prepared for presentations covering the exciting new features of .NET 8, C# 12, Azure, Visual Studio, and so much more. Tune in to learn about the fastest release of .NET yet!
Domain Driven Design: The Good Parts
The greenfield project started out so promising. Instead of devolving into big ball of mud, the team decided to apply domain-driven design principles. Ubiquitous language, proper boundaries, encapsulation, it all made sense.
But along the way, something went completely and utterly wrong. It started with arguments on the proper way of implementing aggregates and entities. Arguments began over project and folder structure. Someone read a blog post that repositories are evil, and ORMs the devil incarnate. Another read that relational databases are last century, we need to store everything as a stream of events. Then came the actor model and frameworks that sounded like someone clearing their throat. Instead of a nice, clean architecture, the team chased the next new approach without ever actually shipping anything.
Beyond the endless technical arguments it causes, domain-driven design can actually produce great software. We have to look past the hype into the true value of DDD, what it can bring to our organizations and how it can enable us to build quality systems. With the advent of microservices, DDD is more important than ever - but only if we can get to the good parts.
> npx create-react-app redux-template --template redux > cd redux-template > yarn start
import { configureStore } from '@reduxjs/toolkit'; import counterReducer from './features/counter/counterSlice'; export default configureStore({ reducer: { counter: counterReducer, }, });
Counter Counter.module.css counterSlice.js
import React, { useState } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { decrement, increment, incrementByAmount, selectCount, } from './counterSlice'; import styles from './Counter.module.css'; export function Counter() { const count = useSelector(selectCount); const dispatch = useDispatch(); const [incrementAmount, setIncrementAmount] = useState(2); return ( <div> <div className={styles.row}> <button className={styles.button} aria-label="Increment value" onClick={() => dispatch(increment())} > + </button> <span className={styles.value}>{count}</span> <button className={styles.button} aria-label="Decrement value" onClick={() => dispatch(decrement())} > - </button> </div> <div className={styles.row}> <input className={styles.textbox} value={incrementAmount} onChange={e => setIncrementAmount(e.target.value)} /> <button className={styles.button} onClick={() => dispatch( incrementByAmount({ amount: Number(incrementAmount) || 0 }) ) } > Add Amount </button> </div> </div> ); }
import { createSlice } from '@reduxjs/toolkit'; export const slice = createSlice({ name: 'counter', initialState: { value: 0, }, reducers: { increment: state => { // Redux Toolkit allows us to 'mutate' the state. It doesn't actually // mutate the state because it uses the immer library, which detects // changes to a "draft state" and produces a brand new immutable state // based off those changes state.value += 1; }, decrement: state => { state.value -= 1; }, incrementByAmount: (state, action) => { state.value += action.payload.amount; }, }, }); export const selectCount = state => state.counter.value; export const { increment, decrement, incrementByAmount } = slice.actions; export default slice.reducer;
- name: برای هر بخش از state، میتوانیم یک نام را تعیین کنیم و این همان عنوانی خواهد بود که میتوانید توسط Redux DevTools مشاهده کنید.
- initialValue: در اینجا میتوانیم مقادیر اولیهای را برای این بخش از state، تعیین کنیم که در مثال فوق، value به مقدار صفر تنظیم شدهاست.
- reducers: این قسمت محل تعریف actionهایی هستند که قرار است state را تغییر دهند. نکته جالب توجه این است که state در هر کدام از متدهای فوق، به ظاهر mutate شده است؛ اما همانطور که به صورت کامنت نیز نوشتهاست، در پشت صحنه از کتابخانهای با عنوان immer استفاده میکند که در عمل بجای تغییر state اصلی، یک کپی از state جدید را جایگزین state قبلی خواهد کرد.
return { ...state, models: state.models.map(c => c.model === action.payload.model ? { ...c, on: action.payload.toggle } : c ) };
state.models.forEach(item => { if (item.model === action.payload.model) { item.on = action.payload.toggle; } });