@bbr:
Załóżmy, że masz tam obiekt 'lista' (klasy Lista), który może przechowywać obiekty klasy Element.
Czy chodzi o to, że masz takiego jak poniższy pseudokod?
// nie są tworzone elementy
lista.wyświetl_zestawienie();
// ale tu już tak:
lista.daj_element(numer_wybranego).daj_tytuł();
Od strony klienta ten kod jest moim zdaniem OK. Problem wystąpić może jednak w kodzie klas Lista/Element. Bo chodzi o to, że wewnątrz np. konstruktora klasy Element masz coś takiego:
class Element {
...
Element(id) {
wynik = baza_danych.wykonaj_zapytanie('SELECT * from Elementy WHERE id = ' + id);
wiersz = wynik.daj_wiersz(0);
this.tytuł = wiersz.daj_pole('tytuł');
}
String daj_tytuł() {
return this.tytuł;
}
}
Natomiast w funkcji Lista::wyświetl_zestawienie masz coś takiego:
class Lista {
...
void wyświetl_zestawienie() {
html_zestawienia = '';
wynik = baza_danych.wykonaj_zapytanie('SELECT * from Elementy');
for (wiersz in wynik) {
html_zestawienia += '<h2>' + wiersz.daj_pole('tytuł') + '</h2>';
}
// a być może powinno być tak:
// for (element in this.elementy) {
// html_zestawienia += '<h2>' + element.daj_tytuł() + '</h2>';
// }
komponent.ustaw_html(html_zestawienia);
}
}
Problemem jest to, że zapytanie wybierające Element jest do pewnego stopnia zdublowane. Klasa Lista ma swój kod zapytania, klasa Element swój. Jest to jakieś tam naruszenie zasady DRY i poniekąd hermetyzacji obiektów klasy Element. Zmiana w tabeli bazy danych Elementy może wpłynąć nie tylko na klasę Element, ale również Lista.
Czy to takie złe? Moim zdaniem, niekoniecznie. Jest dopuszczalne, by Lista -- szczególnie gdy w praktyce pełni funkcję zarządcy -- była stosunkowo ściśle związana z jej Elementami. W razie gdyby okazywało się to upierdliwe, zawsze można refaktoryzować. Tak całkiem "dla idei" to w tym momencie może nie mieć sensu, szczególnie jeśli tak jest faktycznie wygodniej.
Ale ostrzegam: w ten sposób rozumować można wtedy, gdy rzeczywiście projekt jest prowadzony tak, że często robicie refaktoryzacje i nie musicie się z tym kryć. Bo w wielu projektach na refaktoryzacje "nie ma czasu", a potem ciągną się one latami, bo komuś wygodniej było na początku olać jakąś zasadę, a po roku kod się zmienił i zaczęło to wszystkich wkurzać, ale refaktoryzacji już nie zrobili.
A jak chcesz lub faktycznie potrzebujesz zrobić to porządnie, to ZASTOSUJ leniwą inicjalizację. Co więcej, możesz tu zastosować wzorzec projektowy Pełnomocnik (ang. Proxy). Po zastosowaniu tego wzorca, klasa Lista tworzyłaby sobie na samym początku listę obiektów klasy PełnomocnikElementu. Ten pełnomocnik mógłby zainicjalizować niektóre ze swoich pól -- te, których pobranie z bazy nie jest kosztowne -- np. właśnie tytuł. W metodzie Lista::wyświetl_zestawienie() odnoszono by się właśnie do tych pól. A gdyby ktoś -- np. klient klasy Lista -- chciał się odnieść do pozostałych pól, to wtedy PełnomocnikElementu tworzyłby instancję prawdziwego Elementu.
Czy to ma tutaj bardzo duży sens? Niekoniecznie. Bo teraz z kolei klasa PełnomocnikElementu byłaby ściśle związana z Elementem. Fakt, byłoby to oczywiste, że te dwie klasy z definicji są powiązane, ale czy byłoby to o tyle jaśniejsze od faktu powiązania Elementu i Listy/Zarządcy, że gra byłaby warta zachodu?
PS. Nie jestem pewien, czy dobrze zrozumiałem o co w ogóle chodzi, więc może odpisałem nie na temat ;).