ISP — шта је то, принцип раздвајања интерфејса у развоју

Аутор: IT Sectr Објављено: 2026-05-12 Време читања: 9 мин

ISP (Interface Segregation Principle) — четврти принцип SOLID-а који тврди: клијенти не треба да зависе од метода које не користе. Принцип је формулисао Роберт Мартин у контексту пројектовања интерфејса за објектно-оријентисане системе. Као што је описано у књизи Clean Architecture (2017), принцип раздвајања интерфејса захтева стварање уско специјализованих интерфејса уместо једног универзалног, што смањује повезаност и поједностављује уношење измена.

Главно

  • ISP — принцип раздвајања интерфејса, четврти у SOLID-у
  • Клијенти не треба да зависе од метода које не позивају
  • Дебели интерфејси (Fat Interfaces) садрже методе нерелевантне за део клијената
  • Дробљење интерфејса смањује повезаност и повећава поновно коришћење кода
  • ISP је тесно повезан са SRP и Single Responsibility на нивоу интерфејса

Шта је ISP (Interface Segregation Principle)?

ISP (Interface Segregation Principle) — принцип раздвајања интерфејса који забрањује стварање „дебелих“ интерфејса са методама које не користе сви клијенти. Уместо једног интерфејса са десет метода, пројектује се неколико малих интерфејса, сваки за своју групу клијената.

Принцип је увео Роберт Мартин као решење проблема „загађења интерфејса“, када је једна класа приморана да имплементира методе које јој нису потребне само зато што су декларисане у заједничком интерфејсу. У статички типизираним језицима то доводи до празних имплементација или бацања изузетака — директан знак кршења ISP-а.

ISP и SRP се допуњују: SRP говори о одговорности класе, ISP говори о уговорима интерфејса. SRP каже „једна класа — један разлог за промену“, ISP каже „један интерфејс — један клијентски сценарио“. Заједно формирају модуларну архитектуру где сваки елемент система има јасне границе.

Дебели интерфејси и њихове последице

Fat Interface — интерфејс који садржи више метода него што је потребно конкретном клијенту. На пример, интерфејс Worker са методима work, eat, sleep. Робот-радник не би требало да имплементира eat и sleep, али је приморан. Решење — подела на Workable, Eatable, Sleepable. Сваки клијент добија тачно оно што му треба.

У мобилном развоју, дебели интерфејси се јављају у протоколима делегата и DataSource-а. Један протокол може садржати методе за два различита сценарија (уређивање + приказ), иако конкретан екран користи само један од њих.

Како ради принцип раздвајања интерфејса

Имплементација ISP-а почиње анализом клијената сваког интерфејса. Ако два клијента користе различите скупове метода истог интерфејса — интерфејс треба поделити. Сваки нови интерфејс групише методе које се позивају заједно у оквиру једног сценарија.

Механизам поделе: оригинални интерфејс се разбија на неколико уских, од којих сваки наслеђује заједнички део (ако постоји). Клијенти прелазе на зависност од потребног уског интерфејса уместо општег. Класе које имплементирају оригинални интерфејс сада имплементирају само оне уске интерфејсе који су им заиста потребни.

Важно појашњење: степен дробљења се одређује бројем клијената и њихових сценарија. ISP не захтева максимално дробљење (микроинтерфејси са једним методом). То би довело до прекомерне сложености. Циљ је елиминисати зависност клијената од непотребних метода, а не минимизирати величину сваког интерфејса.

Знаци кршења ISP-а

Главни знаци кршења ISP-а укључују: класе које имплементирају интерфејс са празним методама (фиктивна имплементација), бацање изузетка UnsupportedOperationException у имплементацијама, велики број параметара или повратних типова које не користи део клијената, и честе измене интерфејса које погађају само део клијената.

У Android развоју, типичан пример кршења ISP-а је интерфејс OnItemClickListener који укључује методе за клик, дуг клик и превлачење. Ако конкретан екран користи само клик — остале методе остају празне. Решење — подела на OnItemClickListener, OnItemLongClickListener, OnItemSwipeListener.

У iOS развоју, кршење ISP-а се манифестује у делегатима UIKit-а: један протокол садржи методе за различита стања компоненте. UITableViewDelegate укључује методе за приказ, селекцију, уређивање и swipe-акције. Често програмери имплементирају цео протокол са десетак празних метода. Подела на неколико протокола по групама одговорности решава проблем.

Зависност од некоришћених метода

Проблем није само у естетици кода. Када се интерфејс мења (додаје се нови метод), све класе које га имплементирају морају бити ажуриране — чак и оне којима нови метод није потребан. У мобилном развоју са десетинама екрана, то доводи до каскадних промена. ISP изолује сваког клијента од промена које га се не тичу.

Имплицитно кршење ISP-а се дешава кроз параметре конфигурације. Ако метод прима објекат са великим бројем поља, а клијент користи само 2-3 од њих — то је сигнал за поделу. Алтернатива: неколико специјализованих метода са минималним скупом параметара.

У Android развоју, ISP се крши при коришћењу једног SharedPreferencesManager-а за читање и писање свих подешавања апликације. Fragment коме треба само да прочита тему добија зависност од глобалног менаџера са десетак метода за различите типове података. Подела на ThemePreferenceProvider, AuthPreferenceProvider, FeatureFlagProvider — примена ISP-а на нивоу сервиса конфигурације. Сваки провајдер садржи тачно оне методе које су потребне његовим клијентима.

Примери ISP-а у мобилним апликацијама

Размотримо Android пример са интерфејсом за рад са подацима. Кршење ISP-а — један интерфејс за све CRUD операције, иако нису свим клијентима потребне све операције.

kotlin
// Кршење ISP-а: дебели интерфејс
interface UserRepository {
    fun getAll(): List<User>
    fun getById(id: Int): User
    fun save(user: User)
    fun delete(id: Int)
}

// Након примене ISP-а: уски интерфејси
interface UserReader {
    fun getAll(): List<User>
    fun getById(id: Int): User
}

interface UserWriter {
    fun save(user: User)
    fun delete(id: Int)
}

// ReadOnlyViewModel не зависи од метода писања
class ReadOnlyViewModel(
    private val reader: UserReader
)

iOS пример са поделом протокола за рад са медијима:

swift
// Кршење ISP-а: један протокол за цео рад са медијима
protocol MediaService {
    func play(url: URL)
    func pause()
    func stop()
    func upload(data: Data) async -> URL
    func download(url: URL) async -> Data
}

// Након ISP-а: подела на протоколе по одговорности
protocol MediaPlayer {
    func play(url: URL)
    func pause()
    func stop()
}

protocol MediaTransfer {
    func upload(data: Data) async -> URL
    func download(url: URL) async -> Data
}

// PlayerViewModel не зависи од метода учитавања
class PlayerViewModel {
    private let player: MediaPlayer
}

Практични закључак: ISP штити клијенте од промена у независним деловима интерфејса. Подела UserRepository на UserReader и UserWriter значи да промене у save не утичу на ReadOnlyViewModel, и обрнуто. Сваки клијент је изолован од функционалности коју не користи и не захтева промене при доради других делова система.

ISP и SRP — природан пар. SRP одређује да класа треба да има један разлог за промену. ISP примењује исту логику на интерфејсе: интерфејс треба да опслужује један клијентски сценарио. Класа може имплементирати неколико уских интерфејса (сваки одговара једној одговорности), што је чистије од једног дебелог интерфејса са више одговорности.

ISP и OCP су такође повезани: уски интерфејси се лакше проширују. Додавање новог метода у уски интерфејс погађа само његове клијенте. Додавање метода у дебели интерфејс погађа све клијенте — потенцијално кршећи OCP, ако су клијенти приморани да мењају своју имплементацију.

ISP и DIP раде заједно: DIP захтева зависност од апстракција. ISP чини ове апстракције уским и фокусираним. Зависност од широког интерфејса је и даље зависност од апстракције, али „лоше“ апстракције са становишта ISP-a. Четири принципа (SRP, OCP, ISP, DIP) формирају „пирамиду модуларности“: SRP и ISP одређују границе, OCP и DIP — начине проширења и повезивања.

Примена ISP-а у компонентној архитектури

Компонентна архитектура у мобилним пројектима (модули, функционалности, слојеви) има користи од ISP-а на нивоу јавних API-ја. Сваки модул извози уске интерфејсе за своје потрошаче, а не један заједнички фасад. То омогућава промену унутрашње имплементације модула без утицаја на потрошаче који користе само део његове функционалности.

У Android пројектима са Clean Architecture, ISP се примењује на UseCase: сваки UseCase је посебан интерфејс са једним методом invoke или execute. Клијент (ViewModel) зависи само од UseCase-а који му је потребан, а не од целог репозиторијума. То чини зависности транспарентним и тестирабилним.

Често постављана питања

Да ли ISP доводи до прекомерног броја интерфејса?

Да, прекомерно дробљење је могуће. ISP не захтева један интерфејс за сваки метод. Критеријум: постоји ли клијент коме треба само део метода интерфејса. Ако сви клијенти користе све методе — интерфејс не треба делити. Оптимални ниво дробљења одређују реални сценарији коришћења.

Како се ISP примењује на параметре функција?

ISP на нивоу параметара значи: функција не треба да прима објекте са великим бројем поља ако користи само део од њих. Уместо тога, треба преносити само потребне податке или користити специјализоване интерфејсе (на пример, интерфејс Renderable уместо пуног User-а).

Чим се ISP разликује од LSP-а?

LSP говори о исправном наслеђивању и бихевиоралној компатибилности подтипова. ISP говори о пројектовању интерфејса: клијенти не треба да зависе од метода које не користе. LSP одговара на питање „може ли се подкласа користити уместо основне класе?“, ISP — „да ли је клијенту потребан цео интерфејс?“.

Како ISP поједностављује тестирање?

Уски интерфејси поједностављују стварање mock-објеката: тест креира mock са једним-два метода, а не са десет. Што је мање метода у интерфејсу, лакше је симулирати његово понашање. То смањује когнитивно оптерећење програмера теста и смањује вероватноћу грешака у mock-логици.

Када се може одступити од ISP-а?

Ако је интерфејс стабилан и сви клијенти користе све методе — дробљење је сувишно. Типичан пример: UIKit протоколи које је пројектовала Apple. Њихово раздвајање је ризично јер UIKit очекује пуну имплементацију делегата. У таквим случајевима, кршење ISP-а је оправдано стабилношћу API-ја.

Резиме

  • ISP (Interface Segregation Principle) — принцип раздвајања интерфејса, четврти у SOLID-у
  • Клијент не треба да зависи од метода које не користи
  • Дебели интерфејси приморавају класе да имплементирају непотребне методе као празне или са изузецима
  • Раздвајање интерфејса смањује повезаност и изолује клијенте од промена
  • ISP + SRP формирају границе модула: једна одговорност — један уски уговор
  • Mock тестирање се поједностављује: уски интерфејс захтева мање заглушкивања
  • Оптимално дробљење одређују реални клијентски сценарији, а не максимално дробљење

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође