Dwa podejścia w programowaniu

0

Dwa podejścia do pisania programu wykorzystującego obiekt. Poniżej przykład w Javie, w C# jest podobnie.

Podejście 1:

public class XYZ
{
	private int a;
	private int b;
	public XYZ()
	{
		this.a = 0;
		this.b = 0;
	}
	public void SetA(int v)
	{
		this.a = v;
	}
	public void SetB(int v)
	{
		this.b = v;
	}
	public int GetA()
	{
		return a;
	}
	public int GetB()
	{
		return b;
	}
}

XYZ Test = new XYZ
int A = Test.GetA();
int B = Test.GetB();
int C = 1;
int D = 2;
Test.SetA(C);
Test.SetB(D);
 

Podejście 2:

public class XYZ
{
	public int a = 0;
	public int b = 0;
}

XYZ Test = new XYZ
int A = Test.a;
int B = Test.b;
int C = 1;
int D = 2;
Test.a = C;
Test.b = D;
 

Wiem, że jest coś takiego, jak hermetyzacja (uniemożliwienie niekontrolowanej zmiany wartości zmiennych private poza klasą), ale zauważyłem, że to dotyczy pisania kodu, a nie działania programu. Innymi słowy, jeżeli spróbuje się przypisać lub odczytać coś ze zmiennej prywatnej, to program nie skompiluje się, więc nie ma możliwości, żeby istniał działający program, w którym następuje próba dostępu do zmiennej prywatnej i jest jakiś błąd lub wyjątek, bądź cały program sie zamyka.

Rozumiem, że jeżeli chodzi o wielokrotne odczytywanie wartości, która nie jest pamiętana w zmiennej, tylko musi być liczona na podstawie zmiennych za każdym razem, to wtedy stosuje się odpowiednią funkcję wewnątrz klasy.

Natomiast, jak chodzi o operację na jednej zmiennej w klasie, to które podejście jest lepsze?

Cechy obu podejść:

  • Podejście 1 polega na nieco "okrężnym" dostępie do danych, a podejście 2 polega na bezpośrednim dostępie do danych, co może mieć znaczenie przy przetwarzaniu dużej ilości danych.
  • Podejście 2 to brak pomocniczych metod, bez których program może działać, a więc mniej linii kodu w definicji klasy.

Słyszałem, że powinno się stosować podejście 1, ale nie mam logicznego wytłumaczenia, dlaczego. Jednemu koledze napisałem program, w którym stosowałem podejście 2, program działał bezbłędnie, był dokładnie sprawdzony, ale ten kolega, jak zobaczył kod, to zrozumiał go, ale powiedział, że tak nie powinno się programować.

Jakie jest uzasadnienie stosowania podejścia 1 przy pisaniu programów?

0
xxxxxxxxxx napisał(a)

Słyszałem, że powinno się stosować podejście 1, ale nie mam logicznego wytłumaczenia, dlaczego.

Dlatego, że tworzysz w ten sposób zależność od interface'u, nie od wewnętrznej implementacji.

0

Jeśli chodzi o akcesory (gettery i settery) to mają dodatkowe zadanie, wirtualizowanie dostępu do pól. Pola w Javie nie są wirtualizowane (hm nie wiem czy to dobre określenie).

Przykład, który obrazuje o co mi chodzi: http://www.ideone.com/PfLsy
Przy deklaracji pola pole w klasie Dziedzicząca NetBeans słusznie pokazuje ostrzeżenie - Field hides another field.

0
xxxxxxxxxx napisał(a)

Poniżej przykład w Javie, w C# jest podobnie.

Podejście 1 w C# 3.0:

public class XYZ
{
	public int A { get; set;}
	public int B { get; set;}
}

Oszczędności na kodzie nie stwierdzono, resztę chyba napisali już przedmówcy.

0

Dodatkowo gettery i settery dają możliwość sprawdzania poprawności danych na wejściu.

0

Oczywiście. Można dodać w nich jakąś logikę itp Stosowanie bezpośredniego dostępu do pól odcina nam możliwość późniejszej zmiany zachowania obiektu. W ogóle nie jest to zgodne z obiektowością i dziedziczeniem w szczególności.

0

Jeżeli piszesz mały programik to nie ma znaczenia, co wybierzesz. Ale pomyśl o dużych aplikacjach. Jeżeli wyjdziesz, że założenia, że gettery i settery w jakimś przypadku są nieprzydatne, to potem możesz się na tym przejechać. Przecież nie będziesz przeszukiwał całego kodu, gdzie był używany taki niekontrolowany dostęp do pól. Inną sprawą jest jeszcze to, że np. w w takim C++ pole może być obiektem, a dostęp z zewnątrz powinien być raczej dostarczony przez referencję, często referencję na stały obiekt.

0

Mysle, ze temat zjezdza na zle tory... jesli chodzi o uzywanie notacji krotkiej, np dajmy na to

class Human
{

modyfikator dostepu string FirstName;
modyfikator dostepu string LastName;

public Human(string firstName, string lastName)
{
przypisanie wartosci
}
jakies metody
}

Jesli w takim przykladzie ustawimy modyfikatory na public, bedzie mozna ustawiac je z zewnatrz, ale... nie stosuje sie tego od ok 1990 roku, gdyz taki zapis byl baardzo podatny na ataki z zewnatrz i nie ma tu praktycznie zadnej kontroli. Inaczej mowiac zostal zbanowany i programisci stosujacy taki zapis wysylani byli na banicje. Wyewulowalo to trend tworzenia geterow i seterow, np. SetFirstName(string firstName); Z punktu OOP nie jest to najlepsze, bo taka metoda nie jest czynnoscia obiektu, lecz atrybutem. Aczkolwiek jest to do dzisiaj i sprawdza sie doskonale. Powstaly wtedy liczne pomysly co z tym fantem poczac. Niektore IDE pokazuja inne symbole dla atrybutow. Podobna sprawa tyczy sie Eventow. Defakto z punktu widzenia skompilowanego kodu roznica czesto jest znikoma lub rzadna. Tak czy inaczej przypisuje sie zmienna lub referencje. Co do seterow w zapisie nieco dluzszym np

public string FirstName
{ 
get { return this.FirstName; }
set
{ 
if (string.IsNotNull(value) & FirstName.Equals(value, InvariantCulture))
{
this.FirstName = value;
FireFirstNameChanged(); 
}
}
}

jest po prostu rozwinieciem atrybutu o eventy (patterny obserwator i ewentualnie stan lub inne)

Kod nie jest do kompilacji, tylko fragment toku myslenia.

1 użytkowników online, w tym zalogowanych: 0, gości: 1