الكود هو الفكر. تظهر مهمة ، ويفكر المطور في كيفية حلها ، وكيفية التعبير عن المتطلبات في الوظائف والفئات ، وكيفية تكوين صداقات لهم ، وكيفية تحقيق الصرامة والدقة ، وكيفية الحصول على الأعمال التجارية بشكل صحيح. الممارسات والتقنيات والمبادئ والأنماط والمناهج - يجب مراعاة كل شيء وكل شيء يجب أن يتم تذكره.
وإلى جانب ذلك ، نرى وباءًا واسعًا من المديرين والمساعدين والخدمات والمراقبين والمُحكمين والمحولات والأطيان والمستوطنين وغيرهم من الأرواح الشريرة: كل هذا رمز ميت. انه الأغبياء والتكتلات.
أقترح القتال بهذه الطريقة: عليك تقديم البرامج كنص بلغة طبيعية وتقييمها وفقًا لذلك. كيف هذا وما يحدث - في المقال.
جدول دورة المحتويات
- الكائنات
- الإجراءات والخصائص
- الرمز كنص
فاتحة
تجربتي متواضعة (حوالي أربع سنوات) ، لكن كلما عملت أكثر ، كلما فهمت أكثر: إذا كان البرنامج غير قابل للقراءة ، فليس هناك معنى له. من المعروف منذ فترة طويلة أنه تم تذكيره وضربه - فالكود لا يحل بعض المشكلات الآن فحسب ، بل وأيضًا أيضًا: يتم دعمه وتوسيعه وتصحيحه. علاوة على ذلك ، فهو دائمًا: يقرأ.
بعد كل شيء ، هذا هو النص.
تعتبر جماليات الكود كنص موضوعًا رئيسيًا في الدورة. الجماليات هنا هي كأس ننظر من خلاله إلى الأشياء ونقول ، نعم ، إنه جيد ، نعم ، إنه جميل.
في مسائل الجمال والشمولية ، تكون للكلمات أهمية كبيرة. ليقول: "في الوقت الحالي ، تصوراتي في وضع ممل بسبب ارتفاع مستوى الإيثانول في الدم" ليست على الإطلاق مثل: "لقد شربت" .
نحن محظوظون تقريبا برامج تتكون بالكامل من الكلمات.
دعنا نفترض أنك بحاجة إلى تكوين "شخصية تتمتع بالصحة والمانا ، وهو يمشي ، ويهاجم ، ويستخدم نوبات" ، ويمكنك أن ترى على الفور: هناك كائنات (شخصية ، صحة ، مانا ، تهجئة) ، أعمال (المشي ، الهجوم ، الاستخدام) والخصائص ( تتميز الشخصية بالصحة ، mana ، سرعة تعويذات الرهان) - كل هذه ستكون أسماء: فصول ، وظائف ، طرق ، متغيرات ، خصائص وحقول ، في كلمة ، كل ما تنقسم إليه لغة البرمجة.
لكنني لن أميز الفئات عن الهياكل والحقول من الخصائص والأساليب من الدوال: لا تعتمد الشخصية كجزء من سرد على التفاصيل الفنية (يمكن تمثيلها كمرجع أو كنوع مهم). شيء مختلف جوهريًا: أن هذه شخصية وقد أطلقوا عليها Hero
(أو Character
) ، وليس HeroData
أو HeroUtils
.
الآن سآخذ كأس الجماليات وأظهر كيف يتم كتابة بعض الرموز اليوم ولماذا لا تكون مثالية.
الكائنات
في C # (وليس فقط) ، الكائنات - مثيلات الفئات الموضوعة على الكومة ، تعيش هناك لفترة من الوقت ، ثم يقوم جامع البيانات المهملة بإزالتها. يمكن أيضًا إنشاء هياكل على المصفوفة أو المصفوفات الترابطية أو أي شيء آخر. بالنسبة لنا هم: أسماء الفئات ، الأسماء.
الأسماء في التعليمات البرمجية ، مثل الأسماء بشكل عام ، يمكن أن تكون مربكة. نعم ، ونادراً ما ترى اسمًا قبيحًا ، لكنه كائن جميل. خاصة إذا كان Manager
.
مدير بدلا من كائن
UserService
، AccountManager
، DamageUtils
، DamageUtils
، GraphicsManager
، GameManager
، VectorUtil
.
ليست الدقة والملموسة هي التي تهيمن هنا ، بل شيء غامض ، تاركًا مكانًا ما في الضباب. لمثل هذه الأسماء ، الكثير مسموح.
على سبيل المثال ، في أي GameManager
يمكنك إضافة أي شيء يتعلق باللعبة ومنطق اللعبة . بعد ستة أشهر ، سيأتي التفرد التكنولوجي.
أو ، يحدث ذلك ، تحتاج إلى العمل مع facebook. لماذا لا تضع كل الشفرة في مكان واحد: FacebookManager
أو FacebookService
؟ يبدو الأمر بسيطًا بشكل مغر ، لكن مثل هذه النية الغامضة تخلق قرارًا غامضًا بنفس القدر. في الوقت نفسه ، نعلم أن هناك مستخدمين أو أصدقاء أو رسائل أو مجموعات أو موسيقى أو اهتمامات وما إلى ذلك على Facebook. ما يكفي من الكلمات!
لا توجد كلمات كافية فقط: لا نزال نستخدمها. فقط في الكلام العادي ، وليس بين البرامج.
وليس GitUtils
، ولكن IRepository
، ICommit
، IBranch
؛ لا ExcelHelper
، ولكن ExcelDocument
، ExcelSheet
؛ ليس GoogleDocsService
، ولكن GoogleDocs
.
تمتلئ كل منطقة موضوع مع الكائنات. "تميزت الأجسام بفراغات ضخمة" ، "كان القلب ينبض بشراسة" ، "كان المنزل واقفًا" - الأشياء تتحرك ، ويشعرون ، يسهل تخيلها ؛ هم في مكان ما هنا ، ملموسة وكثيفة.
في الوقت نفسه ، تشاهد هذا في بعض الأحيان: في مستودع Microsoft/calculator
- CalculatorManager
باستخدام الطرق: SetPrimaryDisplay
و MaxDigitsReached
و SetParentDisplayText
و OnHistoryItemAdded
...
(ومع ذلك ، أتذكر مرة رأيت UtilsManager
...)
يحدث ذلك بهذه الطريقة: أريد توسيع نوع List<>
بسلوك جديد ، ولا ListUtils
أو ListHelper
. في هذه الحالة ، من الأفضل والأكثر دقة استخدام طرق التمديد فقط - ListExtensions
: فهي جزء من المفهوم ، وليس ListExtensions
من الإجراءات.
أحد الاستثناءات القليلة OfficeManager
.
بالنسبة للباقي ... لا ينبغي تجميع البرامج إذا كانت تحتوي على مثل هذه الكلمات.
العمل بدلا من الكائن
IProcessor
، ILoader
، ISelector
، IFilter
، IProvider
، ISetter
، ICreator
، IOpener
، IHandler
؛ IEnableable
، IInitializable
، IUpdatable
، ICloneable
، IDrawable
، ILoadable
، IOpenable
، ISettable
، IConvertible
.
هنا ، جوهر الجوهر هو إجراء ، وليس مفهومًا ، ويفقد الرمز مرة أخرى صورته وقابليته للقراءة ، ويتم استبدال الكلمة المعتادة بأخرى مصطنعة.
كثير ISequence
هو ISequence
، وليس لا ISequence
. IBlueprint
، وليس ICreator
؛ IButton
، وليس IButtonPainter
؛ IPredicate
، وليس IFilter
؛ IGate
، وليس IOpeneable
؛ IToggle
، وليس IEnableable
.
تحكي قصة جيدة عن الشخصيات وتطورها ، وليس عن كيفية إنشاء المبدع ، وبناء البناية ورسم الرسام. لا يمكن أن يمثل الإجراء كائنًا بالكامل. ListSorter
ليس SortedList
.
خذ DirectoryCleaner
، على سبيل المثال ، كائن يقوم بتنظيف المجلدات على نظام الملفات. هل هي أنيقة؟ لكننا لا نقول أبدًا: "اطلب من منظف المجلد تنظيف D: / Test" ، ودائمًا: "Clean D: / Test" ، لذلك يبدو " Directory
باستخدام الطريقة" Clean
أكثر طبيعية وأقرب.
حالة أكثر حيوية هي أكثر إثارة للاهتمام: FileSystemWatcher
من .NET هو مراقب نظام الملفات الإبلاغ عن التغييرات. ولكن لماذا المراقب بأكمله ، إذا كانت التغييرات نفسها يمكن أن تبلغ أنها حدثت؟ علاوة على ذلك ، يجب أن تكون مرتبطة بشكل لا ينفصم بالملف أو المجلد ، لذلك يجب أيضًا وضعها في Directory
أو File
(باستخدام خاصية Changes
مع القدرة على استدعاء file.Changes.OnNext(action)
).
يبدو أن مثل هذه الأسماء اللفظية تبرر نمط تصميم Strategy
، حيث تصدر تعليمات "بتغليف عائلة الخوارزميات" . ولكن إذا وجدنا بدلاً من " مجموعة من الخوارزميات" كائنًا أصيلًا موجودًا في القصة ، فسنرى أن الاستراتيجية هي مجرد تعميم.
لشرح هذه الأخطاء وغيرها الكثير ، ننتقل إلى الفلسفة.
الوجود يسبق الجوهر
MethodInfo
، ItemData
، AttackOutput
، CreationStrategy
، StringBuilder
، SomethingWrapper
، LogBehaviour
.
يتم توحيد هذه الأسماء من خلال شيء واحد: يعتمد وجودهم على التفاصيل.
يحدث أن يتداخل شيء ما بسرعة مع مهمة: شيء مفقود أو مفقود ، لكن ليس شيئًا ما. ثم تظن: "الشيء الذي يمكن أن يفعله X الآن سيساعدني" - هكذا يكمن الوجود . ثم ، إلى "فعل" X ، تتم كتابة XImpl
- هكذا يظهر الكيان .
لذلك ، بدلاً من IArrayItem
أو IIndexedItem
أو IItemWithIndex
أكثر شيوعًا ، أو ، على سبيل المثال ، في واجهة برمجة تطبيقات Reflection ، بدلاً من الطريقة ( Method
) ، لا نرى سوى المعلومات عنها ( MethodInfo
).
طريقة أكثر صدقًا: في مواجهة الحاجة إلى الوجود ، ابحث عن كيان يقوم بتنفيذ ذلك ، وبما أن هذه هي طبيعتها ، فهناك أشخاص آخرون.
على سبيل المثال ، أرادوا تغيير قيمة string
الكتابة دون إنشاء مثيلات وسيطة - اتضح أن الحل المباشر في شكل StringBuilder
، بينما ، في رأيي ، هو الأنسب - MutableString
.
استرجع نظام الملفات: ليست هناك حاجة إلى DirectoryRenamer
لإعادة تسمية المجلدات ، لأنه بمجرد موافقتك على وجود كائن Directory
، يكون الإجراء موجودًا بالفعل ، لم تجد الطريقة المقابلة في الكود.
إذا كنت ترغب في وصف كيفية أخذ القفل ، فليس من الضروري توضيح أن هذا هو ILockBehaviour
أو ILockStrategy
، وهو أسهل بكثير - ILock
(مع طريقة Acquire
التي تُرجع IDisposable
) أو ICriticalSection
(مع Enter
).
يتضمن هذا أيضًا جميع أنواع Data
Args
Output
Input
Args
Params
(في كثير من الأحيان State
) - الكائنات التي تخلو تمامًا من السلوك ، لأنها تعتبر من جانب واحد.
عندما يكون الوجود أساسيًا ، يتم خلط الحاصل مع العام ، وتكون أسماء الكائنات مربكة - يجب عليك قراءة كل سطر ومعرفة أين ذهب الحرف ولماذا توجد بياناته فقط.
تصنيف غريب
CalculatorImpl
AbstractHero
، AbstractHero
، ConcreteThing
، CharacterBase
.
جميعًا للأسباب نفسها الموضحة أعلاه ، نرى في بعض الأحيان كائنات يتم تحديد مكان لها في التسلسل الهرمي بدقة. مرة أخرى ، يندفع الوجود إلى الأمام ، ونرى مرة أخرى كيف تم إسراع الحاجة العاجلة إلى الكود ، دون النظر في العواقب.
بعد كل شيء ، هل هناك حقا شخص ( Human
) - وريث الشخص الأساسي ( HumanBase
)؟ لكن كيف يتم ذلك عندما يرث Item
AbstractItem
؟
في بعض الأحيان يريدون إظهار أنه لا يوجد Character
، ولكن هناك نوعًا من الشبه "الخام" - CharacterRaw
.
Impl
، Abstract
، Custom
، Base
، Concrete
، Internal
، Raw
- علامة على عدم الاستقرار ، غموض الهندسة المعمارية ، والتي ، مثل البندقية من المشهد الأول ، ستطلق النار لاحقًا.
تكرار
مع الأنواع المتداخلة ، يحدث هذا: RepositoryItem
في Repository
، WindowState
في Window
، HeroBuilder
في Hero
.
التكرار يخترق المعنى ، ويؤدي إلى تفاقم العيوب ، ويساهم فقط في تعقيد النص.
أجزاء زائدة عن الحاجة
لمزامنة مؤشرات الترابط ، غالبًا ما يتم استخدام ManualResetEvent
مع واجهة برمجة التطبيقات التالية:
public class ManualResetEvent {
في كل مرة ، شخصياً ، يجب أن أتذكر كيف يختلف Set
عن Reset
(قواعد غير مريحة) وما "حدث إعادة Reset
يدويًا" بشكل عام في سياق العمل مع التدفقات.
في مثل هذه الحالات ، يكون من الأسهل استخدام الاستعارات بعيدًا عن البرمجة (ولكن بالقرب من الحياة اليومية):
public class ThreadGate { void Open(); void Close(); bool WaitForOpen(); }
بالتأكيد لا يوجد شيء يجب الخلط!
في بعض الأحيان يتعلق الأمر ItemsList
: حدد أن العناصر ليست مجرد Items
، ولكن بالضرورة ItemsList
أو ItemsDictionary
!
ومع ذلك ، إذا لم تكن "قائمة ItemsList
مضحكة ، فستكون " AbstractInterceptorDrivenBeanDefinitionDecorator
ItemsList
من Spring على ما ItemsList
. الكلمات في هذا الاسم هي الخرق التي يخيط بها وحش عملاق. على الرغم من ... إذا كان هذا وحشًا ، فما هو إذن HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor
؟ أمل إرث .
بالإضافة إلى أسماء الطبقات والواجهة ، غالبًا ما يواجه المرء التكرار في المتغيرات أو الحقول.
على سبيل المثال ، يسمى حقل من النوع IOrdersRepository
_ordersRepository
. ولكن ما مدى أهمية الإبلاغ عن تقديم الطلبات بواسطة المستودع؟ بعد كل شيء ، أسهل بكثير - _orders
.
يحدث أيضًا أنه في استعلامات LINQ ، يكتبون أسماء الوسائط الكاملة لتعبيرات lambda ، على سبيل المثال ، Player.Items.Where(item => item.IsWeapon)
، على الرغم من أننا نفهم بالفعل هذا العنصر من خلال النظر في Player.Items
. في مثل هذه الحالات ، أود دائمًا استخدام نفس الحرف - x
: Player.Items.Where(x => x.IsWeapon)
(مع الاستمرار في y
، z
إذا كانت هذه وظائف داخل وظائف).
في المجموع
أعترف ، مع هذه البداية ، لن يكون من السهل العثور على الحقيقة الموضوعية. شخص ما ، على سبيل المثال ، سيقول: كتابة Service
أو عدم الكتابة هي نقطة خلافية ، ضئيلة ، وذوق جيد ، وما الفرق الذي يحدثه إذا نجحت؟
ولكن يمكنك شرب من أكواب المتاح!
أنا مقتنع بأن المسار إلى المحتوى يكمن في النموذج ، وإذا لم ينظر المرء إلى الفكرة ، يبدو أنه قد انتهى. في نص البرنامج ، كل شيء يعمل بالطريقة نفسها: الأسلوب والجو والإيقاع يساعدان على التعبير عن أنفسهم غير مرتبكين ، ولكن بشكل مفهوم ومتفهم.
اسم الكائن ليس فقط وجهه ، بل هو نفسه أيضًا. إنه يحدد ما إذا كان سيكون أثيريًا أو مشبعًا ، أو مجردة أو حقيقي ، جاف أو متحرك. الاسم يتغير - المحتوى يتغير.
في المقال التالي سنتحدث عن هذا المحتوى بالذات وما يحدث.