RSS

Trudno jest uciec przed hermetyzacją

Liczba odsłon: 54

Hermety­za­cja to tech­ni­ka pro­gra­mo­wa­nia obiek­to­we­go, w któ­rej za­bro­nio­ny (i za­blo­ko­wa­ny) jest do­stęp do wszyst­kich pól po­szcze­gól­nych obiek­tów. Ustala­nie i po­bie­ra­nie war­toś­ci pól od­by­wa się wy­łącz­nie za po­mo­cą pub­licz­nych me­tod; na przy­kład:

class Liczba {
   public:
   Liczba() throw() : liczba(0) {}
   void UstawLiczbe(const int l) throw()
      { liczba = l; }
   int PobierzLiczbe() const throw()
      { return liczba; }
   private:
   int liczba;
};

Hermety­za­cja prze­de wszyst­kim unie­za­leż­nia inter­fejs da­nej kla­sy od jej im­ple­men­tac­ji. W wie­lu przy­pad­kach pra­wid­ło­wa her­me­ty­za­cja umoż­li­wia bar­dzo po­waż­ne zmia­ny spo­so­bu prze­cho­wy­wa­nia da­nych w ra­mach kla­sy (na przy­kład za­stą­pie­nie sta­tycz­nych struk­tur da­nych dyna­micz­ną alo­ka­cją pa­mię­ci) bez ko­niecz­noś­ci wpro­wa­dza­nia zmian w resz­cie pro­gra­mu. Hermety­za­cja sta­no­wi też naj­lep­szy spo­sób wpro­wa­dze­nia ry­go­ry­stycz­nej we­ry­fi­ka­cji da­nych za­pi­sy­wa­nych w obiek­cie.

Stosowa­nie her­me­ty­za­cji wy­ma­ga jed­nak na­pi­sa­nia spo­rej iloś­ci ko­du, co mo­że znie­chę­cać pro­gra­mis­tę. Szczególnie w przy­pad­ku, gdy two­rzo­na kla­sa jest ma­ła i pros­ta, a jej ce­lem jest wy­łącz­nie prze­cho­wy­wa­nie kil­ku liczb lub na­pi­sów, po­mysł stwo­rze­nia dwóch funk­cji dla każ­de­go z pól wy­da­je się ma­ło atrak­cyj­ny.

Warto jed­nak nie igno­ro­wać her­me­ty­za­cji i sto­so­wać ją na­wet, jeś­li po­cząt­ko­wo wy­da­je się być ma­ło po­trzeb­na. Po pros­tu bar­dzo szyb­ko i tak się ją wpro­wa­dza, opóź­nia­jąc jed­nak in­ne pra­ce.

Siedzę ostat­nio nad do­syć spo­rym pro­jek­tem pro­gra­mi­stycz­nym, zwią­za­nym z ob­rób­ką da­nych za­pi­sa­nych w pli­kach tek­sto­wych i ba­zach da­nych (jest to zresz­tą je­den z po­wo­dów, dla któ­rych Świat Owo­ców ostat­ni­mi cza­sy świe­ci ta­ki­mi pust­ka­mi). Wczoraj aku­rat koń­czy­łem mo­duł słu­żą­cy do wczy­ty­wa­nia da­nych za­pi­sa­nych w pli­ku CSV (wy­ciąg z ze­wnętrz­nej ba­zy da­nych) i umiesz­cza­nia ich w tab­li­cy struk­tur prze­cho­wu­ją­cych (na ra­zie) trzy po­la: kod, naz­wę ele­men­tu i sto­wa­rzy­szo­ną z nim war­tość licz­bo­wą. Swoją dro­gą, od­czy­ta­nie pli­ku CSV wy­da­wa­ło­by się być pros­te, w prak­ty­ce jed­nak zaw­sze wy­cho­dzą na świat­ło dzien­ne ja­kieś nie­przy­jem­ne wy­jąt­ki; z te­go po­wo­du zde­cy­do­wa­łem się stwo­rzyć uni­wer­sal­ną kla­sę, w ra­mach któ­rej mo­gę bez stre­su za­da­wać znak de­li­mi­te­ra czy zmie­niać spo­sób inter­pre­tac­ji zna­ków cu­dzy­sło­wu.

Pierwsza wer­sja pro­gra­mu te­sto­we­go wczy­ty­wa­ła da­ne bez­poś­red­nio do pól struk­tu­ry i dzia­ła­ła świet­nie. Ponie­waż jed­nak pro­gram miał być nie­za­wod­ny (wy­ko­rzys­ta­nie w prze­myś­le), po­sta­no­wi­łem do­pi­sać frag­ment ko­du od­po­wie­dzial­ny za we­ry­fi­ka­cję sen­sow­no­ści od­czy­ta­nych da­nych i zgła­sza­nie (w for­mie sytu­acji wy­jąt­ko­wej) ko­dów i nazw za­wie­ra­ją­cych nie­po­praw­ne zna­ki oraz war­toś­ci licz­bo­wych nie na­le­żą­cych do pra­wid­ło­we­go prze­dzia­łu.

Najbardziej sen­sow­nym miej­scem na umiesz­cze­nie we­ry­fi­ka­cji po­praw­noś­ci za­war­toś­ci pól kla­sy jest oczy­wiś­cie sa­ma kla­sa. Dodałem do niej za­tem trzy me­to­dy usta­la­ją­ce war­tość każ­de­go z pól z osob­na i – przy okaz­ji – spraw­dza­ją­ce po­praw­ność wpi­sy­wa­nych w te po­la da­nych. W ten spo­sób w prak­ty­ce za­her­me­ty­zo­wa­łem kla­sę: wy­star­czy­ło te­raz do­pi­sać trzy me­to­dy po­bie­ra­ją­ce za­war­tość tych pól (ty­pu inline, by nie spo­wal­niać pro­gra­mu nie­po­trzeb­ny­mi sko­ka­mi), zmie­nić atry­but wi­docz­no­ści pól z public na private — i go­to­we!

Morał: na­wet jeś­li po­cząt­ko­wo wy­da­je się, że her­me­ty­za­cja sta­no­wi prze­rost for­my nad treś­cią, a jej zig­no­ro­wa­nie nie po­ciąg­nie za so­bą żad­nych kon­sek­wen­cji, nad­spo­dzie­wa­nie częs­to po­trze­ba za­her­me­ty­zo­wa­nia kla­sy po­ja­wia się już w trak­cie ko­rzys­ta­nia z niej. No, chy­ba, że two­rzo­ne opro­gra­mo­wa­nie nie mu­si być bez­piecz­ne i nie­za­wod­ne…