Як визначити рівні абстракції


35

Сьогодні я читав книгу під назвою "Чистий код", і я натрапив на абзац, коли автор говорив про рівні абстракції за функцією, він класифікував якийсь код як низький / проміжний / високий рівень абстракції.

Моє запитання - які критерії визначення рівня абстракції?

Я цитую абзац з книги:

Щоб переконатися, що наші функції роблять «одне», нам потрібно переконатися, що твердження в межах нашої функції всі на одному рівні абстракції. Неважко зрозуміти, як Лістинг 3-1 порушує це правило. Існують такі концепції, які знаходяться на дуже високому рівні абстракції, такі як getHtml (); інші, що знаходяться на проміжному рівні абстракції, такі як: String pagePathName = PathParser.render (pagePath); та інші, які мають надзвичайно низький рівень, такі як: .append ("\ n").


Відповіді:


27

Автор пояснює, що в підрозділі "Код читання від верху до низу" частини, яка розповідає про абстракції (міна ієрархічного відступу):

[...] ми хочемо, щоб програма могла читати так, ніби це набір пунктів TO , кожен з яких описує поточний рівень абстрагування та посилається на наступні пункти TO на наступному рівні вниз.

  • Для включення налаштувань та сходів ми включаємо установки, потім включаємо вміст тестової сторінки, а потім включаємо пробки.
    • Для включення налаштувань ми включаємо налаштування набору, якщо це набір, тоді ми включаємо звичайні настройки.
      • Щоб включити налаштування набору, ми шукаємо батьківську ієрархію сторінки "SuiteSetUp" і додаємо оператор включення разом із контуром цієї сторінки.
        • Для пошуку батьків ...

Код, що йде разом з цим, буде приблизно таким:

public void CreateTestPage()
{
    IncludeSetups();
    IncludeTestPageContent();
    IncludeTeardowns();
}

public void IncludeSetups()
{
    if(this.IsSuite())
    {
        IncludeSuiteSetup();
    }

    IncludeRegularSetup();
}

public void IncludeSuiteSetup()
{
    var parentPage = FindParentSuitePage();

    // add include statement with the path of the parentPage
}

І так далі. Кожен раз, коли ви заглиблюєтесь в ієрархію функцій, вам слід змінювати рівні абстракції. У наведеному вище прикладі IncludeSetups, IncludeTestPageContentі IncludeTeardownsвсі знаходяться на одному рівні абстракції.

У прикладі, наведеному в книзі, автор припускає, що велику функцію слід розділити на більш дрібні, які є дуже конкретними і роблять лише одне. Якщо зробити все правильно, функція відновлення буде виглядати аналогічно наведеним тут прикладам. (Реконструйована версія наведена в Лістингу 3-7 книги.)


10

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

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

Те саме з програмним забезпеченням. Щоразу, коли ви програмуєте, як радить книга, вам потрібно думати про своє програмне забезпечення як про шари. Дана програма може легко мати більше ста шарів. Внизу у вас можуть бути інструкції по збірці, які працюють на центральному процесорі, на більш високому рівні ці інструкції можуть поєднуватися для формування підпрограм вводу / виводу диска на ще більш високому рівні, вам не потрібно працювати з Disk I / O безпосередньо, оскільки ви можете використовувати функції Windows просто для відкриття / читання / запису / пошуку / закриття файлу. Це все абстракції ще до того, як ви перейдете до власного коду програми.

У межах вашого коду шари абстракції продовжуються. Можливо, у вас є підпрограми маніпулювання рядками / мережею / даними нижчого рівня. На більш високому рівні ви можете комбінувати ці підпрограми в підсистеми, що визначають управління користувачами, рівень користувальницького інтерфейсу, доступ до бази даних. Ще один рівень цих підсистем може бути об'єднаний в серверні компоненти, які об'єднуються і стають частиною більшої корпоративної системи.

Головне для кожного з цих шарів абстрагування полягає в тому, що кожен з них приховує деталі, викриті попереднім шаром (ими), і представляє дуже чистий інтерфейс, який повинен бути використаний наступним шаром вгору. Щоб відкрити файл, ви не повинні знати, як писати окремі сектори або які апаратні переривання обробляються. Але якщо ви почнете подорожувати по ланцюгу шару абстракції, ви, безумовно, зможете простежити від виклику функції Write (), аж до точної інструкції, що надсилається на контролер жорсткого диска.

Те, що пропонує вам зробити автор, коли ви визначаєте клас чи функцію, подумайте, який саме ви є шаром. Якщо у вас є клас, який керує підсистемами та об’єктами користувача, той самий клас не повинен виконувати маніпуляції з рядком низького рівня або містити цілу купу змінних лише для здійснення дзвінків з сокета. Це було б порушенням схрещування шарів абстракції, а також того, щоб мати один клас / функцію, робити лише одне (SRP - єдиний принцип відповідальності).


2

Моє запитання - які критерії визначення рівня абстракції?

Рівень абстракції повинен бути очевидним. Це абстрактно, якщо це частина проблемної області - не частина мови програмування. Важко бути більш зрозумілим, ніж "високо абстрактний" == "не реальний" == "проблемний домен". І "не абстрактна == конкретна == частина мови". Вирішити рівень абстракції слід тривіально. Тут взагалі не повинно бути тонкощів.

.append("\n")не є абстрактним. Він просто кладе символ на рядок. Це було б конкретно. Не абстрактно.

String pagePathName = PathParser.render(pagePath);угод з Strings. Конкретні речі. Частково про конкретні особливості мови програмування. Частково працює з абстрактними поняттями "шлях" та "парсер".

getHtml(); Анотація Має справу з "Розмітка" та речі, які не є тривіальними, конкретними, мовними особливостями.

Анотація == не мовна особливість.

Конкретна == мовна особливість.


1
Якщо ви визначаєте реферат як якість, яка описує ті речі, які створює програміст, тобто абстракції, згенеровані програмістом, то я схильний погодитися з вашими визначеннями слів. Але всі мови програмування - це абстракції над чимось більш конкретним. Вибір мови програмування значною мірою визначає, на якому рівні абстракції ви починаєте.
Роберт Харві

1

Я думаю, що рівень абстракції простий ... якщо рядок коду безпосередньо не реалізує єдину відповідальність методу, це ще один рівень абстракції. Наприклад, якщо назва мого методу - SaveChangedCustomers () і приймає список ВСІХ клієнтів як параметр, одна відповідальність полягає в збереженні будь-яких клієнтів у списку, який був змінений:

foreach(var customer in allCustomers)
{
    if (CustomerIsChanged(customer)
        customer.Save();
}

Часто замість виклику методу CustomerIsChanged () ви знайдете логіку, щоб визначити, чи змінився клієнт, вбудований у цикл foreach. Визначення того, чи змінився запис клієнта, НЕ відповідальність цього методу! Це різний рівень абстракції. Але що робити, якщо логіка зробити це визначення лише одним рядком коду? Не має значення !!! Це різний рівень абстракції, і він повинен бути поза цим методом.

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