Днес прочетох за нещо, наречено Meyer’s Uniform Access Principle. Това е един много интересен прицип касаещ ООП езиците. Гласи горе-долу следното:
Атрибутите на един обект трябва да се достъпват чрез нотация, която не позволява да се различи дали те са имплементирани чрез запис или чрез изчисление.
Иначе казано, line.length
не трябва да издава дали става въпрос за поле или метод, изчисляващ разстоянието между двата края. Това е много хубава идея, понеже промотира любимите ми думички – абстракция и енкапсулация. Та, замислих се доколко това важи в езиците, които ползвам.
Ruby
Тук положението е най-добре. В Ruby дори няма концепцията за публично поле – точката служи единствено за извикване на метод. Но комбинацията незадължителните скоби и attr
/attr_accesor
имплементира този принцип естествено.
attr :start, true
attr :end, true
def length
start.distance_to end
end
end
line = Line.new
line.start = Point.new(0, 0)
line.end = Point.new(3, 4)
puts line.length
Python
При питона положението е по-средно. Има ясно разделение между функции и полета. Границата между тях може да бъде изтрита като се ползва property
, но това вкарва синтактичен шум за да станат нещата чисто.
Друг проблем идва, от това че length
може да бъде или само поле или само метод. За да следвате принципа трябва да вземете решение дали ще се обръщате като line.length
или line.length()
. Докато първото е в духа на UAP, то ви води към едно коварно усложнение. В повечето класове ще има доста методи, които не могат или не е логично да се реализират като property
. Така често потребителите на вашия код ще се чудят „Тук да слагам ли скоби или не?“. Това ще създаде повече усложнения, отколкото удобства.
Java
Стандарта в Java повелява да не показваме полетата публично и да скриваме за двойка методи getFoo/setFoo
. Това донякъде скрива дали става въпрос за поле или изчисление, но само частично – думичките get
и set
издават, че става въпрос за property. Отвъд това ми се струва валидна имплементация. Предимството е, че 99% от Java кода ще уважава този стандарт. Недостатъка са двата шаблонни метода за всяко property, създаващи единствено шум.
Някъде видях идеята вместо getSize()/setSize(5)
да се ползва size()/size(5)
. Това ще е съвсем в духа на UAP, но в остър разрез със стандартите на Java.
Накратко
Ruby поддържа този принцип отръки. Да отворим бира на Matz. Java и Python могат да го добутат, но според мен това ще доведе единствено до усложнения за програмиста.