Як занадто багато змінних примірників призводить до дублювання коду?


19

Відповідно до Refactoring to Patterns :

Коли клас намагається зробити занадто багато, він часто виявляється як занадто багато змінних екземплярів. Коли у класу занадто багато змінних примірників, дублюваний код не може відстати.

Як занадто багато змінних примірників призводить до дублювання коду?


2
Простіше кажучи: nбулеві змінні, наприклад, створюють внутрішній простір стану 2^n. Частіше за все, хоча ваш об'єкт не має такої кількості спостережуваних станів , а тому, що ви переповнили весь цей стан одним об'єктом, всередині вам все одно доведеться їх обробляти.
biziclop

Відповіді:


23

Занадто велика кількість змінних екземплярів безпосередньо не пов'язана з дублюючим кодом, або навпаки. Це твердження в цій загальності є хибним. Можна перекинути два окремі класи без дублювання коду до одного класу - це створює новий клас з нерозділеними обов'язками і занадто великою кількістю змінних примірників, але все ще не дублює код.

Але коли ви знайдете клас із занадто великою кількістю відповідальності в реальному коді реального світу, великі шанси програміст, який його написав, не піклувався про чистий код або принципи SOLID (принаймні, не в той час, коли він писав цей код), тому його не навряд чи ви знайдете там інші запахи коду, як дублікат коду.

Наприклад, анти-візерунок "копіювати-вставити повторно використовувати" часто застосовується шляхом копіювання старого методу та внесення до нього невеликих модифікацій без належного рефакторингу. Іноді, щоб зробити цю роботу, доводиться дублювати змінну члена і трохи змінювати цю змінну. Це може призвести до класу із занадто великою кількістю змінних екземплярів (точніше: занадто багато дуже схожих змінних екземплярів). У такій ситуації подібні змінні екземпляра можуть бути показником для повторного коду в інших місцях класу. Однак, як ви зазначали, це штучний приклад, і я з цього не зробив би загального правила.


11

Занадто багато змінних примірників означає занадто багато стану. Занадто багато стану призводить до дублювання коду, який лише трохи відрізняється для кожного із станів.

Це класичний одиночний конкретний клас, який робить занадто багато речей, які мають бути підкласами чи композиціями.

Знайдіть кілька класів, у яких є занадто багато змінних екземплярів, ви побачите, що вони підтримують занадто багато стану і мають безліч дублюваних кодових шляхів, які лише трохи спеціалізовані для кожного випадку, але настільки перекручені, що їх неможливо розбити на методи багаторазового використання. Це також одне з найбільших джерел side effects.

З цього принаймні є один виняток, який не підпадає під цю категорію і є простим способом її усунення. ImmutableОб'єкти не мають цієї проблеми, оскільки вони є фіксованим станом, немає шансів на згорнуте управління державою чи побічні ефекти.


7

Висловлювання, яке ви цитуєте, має розглядатися в конкретному контексті.

За моїм досвідом, я не можу підтвердити, що "багато змінних екземплярів взагалі вказують на дублюваний код". Також зауважте, що це належить до "кодових запахів", і там нібито суперечать запахи. Подивіться тут:

http://c2.com/cgi/wiki?CodeSmell

Забавно, що ви знайдете "занадто багато змінних екземплярів", настільки ж хороший запах коду, як і "занадто мало змінних екземплярів".

Але існують проблеми із змінними екземплярів, будь то занадто мало або занадто багато:

  1. Кожна змінна інстанція може означати певний статус об'єкта. Стати завжди потребує ретельного лікування. Ви повинні переконатися, що ви охопили всі можливі комбінації стати, щоб уникнути несподіваної поведінки. Ви завжди повинні чітко розуміти: який статус зараз має мій об’єкт? З цього кута, багато змінних примірників можуть вказувати на те, що клас став неможливим. Це також може вказувати на те, що клас виконує занадто багато завдань, оскільки йому потрібно стільки статистів.

  2. Кожна змінна інстанція вимагає від вас контролю, які методи змінюють змінну в який спосіб. Тож раптом ти вже не знаєш усіх кухарів, які готують. Одна з них, запрограмована втомлено пізно вночі, зіпсує ваш суп. Знову ж таки: занадто багато таких змінних призведе до важкого проникнення коду.

  3. Інша сторона: занадто мало змінних екземплярів може призвести до того, що багато методів повинні обробляти свою інформацію занадто багато роботи і з занадто великими параметрами. Ви відчуваєте це, якщо ви даєте багатьом своїм методам певний рівний параметр, і всі методи якимось чином роблять дуже подібну річ з цим параметром. У цій ситуації ваш код почне розквітати. Ви прокрутите багато екранів вгору і вниз, щоб зібрати деякі прості речі. Тут може допомогти рефакторинг: ввести одну змінну екземпляра та один чіткий вхід до неї. Потім звільніть усі методи.

  4. І останнє, але не менш важливе: якщо багато змінних екземплярів класу мають свій сетер і getter кожен, то це може означати, що інші класи не використовують цей перший клас правильно. Йде дискусія на тему " Чому геттери та сетери - це зло ". Коротше кажучи, ідея полягає в тому, що якщо клас Rectangleпропонує декілька getX(), а десятки інших класів використовують rectangle.getX(), ви пишете код, який не є надійним щодо "ефекту пульсації" (наскільки навколо зміни коду впливають на інший код). Просто запитайте, що станеться, якщо ви зміните тип з intна double? Відповідно до цієї дискусії, багато rectangle.getX()дзвінків насправді мають бути краще як дзвінкиrectanlge.calculateThisThingForMe(). Отже, дуже опосередковано дублюваний код може виникнути з багатьох змінних екземплярів, оскільки багато класів навколо використовують багато геттерів і сетерів, які роблять дуже подібні речі, тобто скопійовані речі, які краще перемістити всередину класу.

Багато або кілька змінних екземплярів залишається постійною компромісною зміною, змінюючи обидва способи, поки програмне забезпечення зростає.


Цитата R-to-P занадто загальна, тому мені подобається ця відповідь. Мій відбір: якщо ми виставимо достатню кількість властивостей, клієнт може, і буде, візьмемо їх і запишемо її власну версію заданої функції - №4 вище. Проблема може настільки ж глибоко, як і об'єктна композиція - див. №2: Я занадто часто бачу це в нашому коді. (а) "чому вони не використовували клас <що б то не було> (щоб виправити частину цього неорганізованого стану)?" або (b) "Чому вони не склали новий клас? Я не можу все це відслідковувати." І, безумовно, у нас є кілька класів, що внутрішньо дублюють функціональність через відсутність узгодженого класу.
radarbob

6

Простіше кажучи: поганий поділ проблем в коді, призводить до коду, який не є модульним, призводить до поганого повторного використання, призводить до дублювання коду.

Якщо ви ніколи не намагаєтеся повторити функціональність, ви не отримаєте дублювання коду, і багато змінних екземплярів не будуть проблемою.

Якщо ви спробуєте повторити функціональність, монолітний код, який не є модульним, не може бути використаний повторно. Це робить занадто багато і може робити лише те, що робить. Щоб зробити щось подібне, але не те саме, "простіше" вирізати та вставити, ніж розбити монолітний код. Досвід програмистів знає, що дублюваний код - це дорога в пекло.

Отже, хоча багато змінних екземплярів сама по собі не є першопричиною проблеми, але проблема сильна "запахом".

Мова "не може бути далеко позаду" слабша, ніж сказати "треба обов'язково слідувати", тому автор не стверджує, що це має відбутися, але в кінцевому підсумку відбудеться; якщо вам потрібно повторно використовувати функціонал, але не можете, оскільки код не є модульним.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.