Python - zapisz, wczytaj i utwórz w jednym obiekcie

0

Posiadam obiekt który odpowiada za pliki projektu. Tzn spina wszystko w całość(backupy, pliki projektu itp.).
Posiada on zasadniczo trzy, interesujące nas w tym momencie zadania(inne nie mają wpływu na zagadnienie):

Utwórz projekt i zapisz jego pliki w danej lokalizacji
Wczytaj projekt z określonej lokalizacji
Zapisz zmiany w projekcie(oddzieliłem ponieważ taka metoda nie wymaga aż tak dużej ilości argumentów, wykonuje dużo mniej operacji, poza tym nie zmienia wartości które wymagane są do podania jako argumenty pierwszej metody)

W teorii wszystko gra, tylko, że:

Nie można w konstruktorze przyjąć określonej listy argumentów i wykonać tworzenia bądź wczytywania projektu ponieważ nie wiadomo jeszcze co programista zamierza zrobić - utworzyć nowy, czy wczytać istniejący projekt(a więc wiele wartości które przy tworzeniu są wymagane jako argumenty pobrać z plików projektu).

Jeśli konstruktor nie będzie przyjmował żadnych argumentów(wydawało by się to najlepsze rozwiązanie) to można by zrobić potem object.load bądź object.create, ale wtedy gdyby ktoś skorzystał z object.save_changes zanim wczytałby pliki projektu lub utworzył projekt, mogłoby dojść do błędu ponieważ wiele potrzebnych zmiennych nie byłoby utworzonych. Można by wtedy rzucić wyjątkiem, ale nie jestem pewien czy to nie byłoby sprzeczne z normami które stosujemy w Pythonie. Nie powinno być chyba tak, że jedna metoda wyrzuca wyjątek i odmawia współpracy, jeśli wcześniej nie wywołamy innej.

Myślałem o przeładowaniu w konstruktorze tak, aby tworzona instancja obiektu mogła(w zależności od podanych argumentów) być jednocześnie tworzeniem projektu bądź jego wczytywaniem. Natomiast mam wrażenie - być może nie prawdziwe - że w Pythonie unika się stosowania przeładowań, a już szczególnie w konstruktorze. Nie wiem też, czy takie coś byłoby odpowiednio intuicyjne dla programisty. Mam wrażenie, że lepiej byłoby robić instance = object() i potem object.load(argumenty metody) bądź object.create(argumenty metody). Natomiast nie wiem jak to wszystko zrobić tak, aby to było zgodnie ze sztuką.

1

Bardzo dziwnie to wygląda. Co masz dokładnie na myśli mówiąc "projekt"?

0

Dla zajawki i do portfolio tworzę prosty edytor zdjęć. Zapisuje on projekt w formie pliku JSON i do tego folder który zawiera bieżącą wersje zdjęcia w pliku graficznym oraz jego kopie zapasowe z poprzednimi zmianami. Klasa project miała odpowiadać za zarządzanie tym. Od tworzenia kopii mam za to osobną klasę, która jest używana w tym wypadku wewnątrz klasy projekt, ale jest napisana tak, że działa w pełni niezależnie sama w sobie.

0
iProgramist napisał(a):

Dla zajawki i do portfolio tworzę prosty edytor zdjęć. Zapisuje on projekt w formie pliku JSON i do tego folder który zawiera bieżącą wersje zdjęcia w pliku graficznym oraz jego kopie zapasowe z poprzednimi zmianami. Klasa project miała odpowiadać za zarządzanie tym. Od tworzenia kopii mam za to osobną klasę, która jest używana w tym wypadku wewnątrz klasy projekt, ale jest napisana tak, że działa w pełni niezależnie sama w sobie.

A jakie funkcje miałbym mieć ten edytor zdjęć? Nie mów o tym na jakie klasy podzielisz funkcje, tylko opisz co miałoby się dać móc zrobić Twoim edytorem?

0

To znaczy w sumie klasa project ma również działać w pełni niezależnie i działać podpięta do innych programów. Ma mieć możliwość automatycznego używania klasy odnośnie historii zmian, móc tworzyć projekt, otwierać i zapisywać w nim zmiany. Zamiast pliku graficznego może być w zamyśle każdy inny.

Natomiast odpowiadając na Twoje pytanie: plany są różne co do przyszłej funkcjonalności. Na początek chciałbym aby dało się nakładać proste filtry na zdjęcia, ich fragmenty oraz mieć proste rysowanie takie jak kwadraty, czy odręczne rysowanie. Klasę która przyjmuje obraz bądź jego fragment i nakłada wybrany filtr z danymi parametrami mam już również gotową. Po prostu chciałbym mieć plik w którym trzymałbym dane o konfiguracji programu(format json wybrałem), folder w którym będzie znajdował się plik źródłowy w aktualnie zapisanej wersji oraz jeśli funkcja zapamiętywania zmian będzie włączona, to ilość określona wcześniej zmian, będzie zapisywana w formie plików backup. Będzie można dzięki temu łatwo w programie używać funkcji cofnij czy powtórz, a także odzyskać daną wersję w razie awarii. Nie będą to pliki tymczasowe więc nawet po zamknięciu programu i ponownym uruchomieniu będzie można cofać wciąż zmiany, powtarzać itp.

Natomiast o ile dobrze rozumiem zamysł SOLID staram się robić program modułowo, czyli żeby na ile się dało, to dane części programów były niezależne. Tzn. dowolnie można podmienić GUI bądź utworzyć interfejs konsolowy, można używać historii cofania w dowolny sposób i do dowolnych plików, a klasa projektu jak wspominałem będzie mogła być używana równie dobrze np. do edytora tekstu. Po prostu będzie wczytywany plik źródłowy zamiast graficzny, to np. txt, doc itp.

0
iProgramist napisał(a):

To znaczy w sumie klasa project ma również działać w pełni niezależnie i działać podpięta do innych programów. Ma mieć możliwość automatycznego używania klasy odnośnie historii zmian, móc tworzyć projekt, otwierać i zapisywać w nim zmiany. Zamiast pliku graficznego może być w zamyśle każdy inny.

Czyli chcesz zrobić bibliotekę do zarządzania dowolnym projektem, nie tylko do projektów graficznych?

iProgramist napisał(a):

Natomiast odpowiadając na Twoje pytanie: plany są różne co do przyszłej funkcjonalności. Na początek chciałbym aby dało się nakładać proste filtry na zdjęcia, ich fragmenty oraz mieć proste rysowanie takie jak kwadraty, czy odręczne rysowanie. Klasę która przyjmuje obraz bądź jego fragment i nakłada wybrany filtr z danymi parametrami mam już również gotową. Po prostu chciałbym mieć plik w którym trzymałbym dane o konfiguracji programu(format json wybrałem), folder w którym będzie znajdował się plik źródłowy w aktualnie zapisanej wersji oraz jeśli funkcja zapamiętywania zmian będzie włączona, to ilość określona wcześniej zmian, będzie zapisywana w formie plików backup. Będzie można dzięki temu łatwo w programie używać funkcji cofnij czy powtórz, a także odzyskać daną wersję w razie awarii. Nie będą to pliki tymczasowe więc nawet po zamknięciu programu i ponownym uruchomieniu będzie można cofać wciąż zmiany, powtarzać itp.

Z tego co rozumiem; to chcesz zrobić program do edycji obrazów; ale chcesz w nim również napisać reużywalny moduł zdolny do zapisu dowolnego projektu, tak?

0

Właściwie tak. Robię tą klasę przystosowaną do mojego programu, ale staram się pozostawić elastyczność.

0
iProgramist napisał(a):

Właściwie tak. Robię tą klasę przystosowaną do mojego programu, ale staram się pozostawić elastyczność.

Ale masz jakiś konkretny powód za tym? Bo to jest popularne zjawisko wśród początkujących w programowaniu; żeby starać się zrobić coś dużo bardziej reusable niż jest na to jakakolwiek potrzeba.

Gdybym miał Ci coś doradzić, mając na uwadze Twój dobry rozwój, to raczej bym odradzał takie "pozostawienie elastyczności". Zrób po prostu edytor edycji zdjęć, jak już zrobisz, to wtedy sie zastanowimy jak go oddzielić od projektu, oki?

0

@TomRiddle:

  1. To nie zmienia faktu, nadal problem jest taki sam. Ponieważ dokładnie takiego obiektu potrzebuję. A to, że przy okazji można mu podłożyć inny plik niż graficzny to efekt uboczny.
  2. Czy to o czym mówisz, nie kłóci się z SOLID? Ja zacząłem starać się robić uniwersalnie ponieważ zacząłem czytać o czystym kodzie i SOLID. Podobno każda klasa powinna być na tyle niezależna i możliwa do uniwersalnego użycia, na ile to możliwe. Wyprowadź mnie z błędu jeśli coś źle rozumiem.
0
iProgramist napisał(a):
  1. To nie zmienia faktu, nadal problem jest taki sam. Ponieważ dokładnie takiego obiektu potrzebuję. A to, że przy okazji można mu podłożyć inny plik niż graficzny to efekt uboczny.

Jeśli to efekt uboczny, to spoko.

Jeśli jednak miałbyś dokładać specjalnie starań żeby zrobić je bardziej reusable niż teraz są; to to raczej zły pomysł.

  1. Czy to o czym mówisz, nie kłóci się z SOLID? Ja zacząłem starać się robić uniwersalnie ponieważ zacząłem czytać o czystym kodzie i SOLID. Podobno każda klasa powinna być na tyle niezależna i możliwa do uniwersalnego użycia, na ile to możliwe. Wyprowadź mnie z błędu jeśli coś źle rozumiem.

Nie, raczej nie. Tzn; to co mówisz nie jest tak super znowu nie prawdą, ale jest mylące. Zbyt duże uproszczenie.

W SOLID chodzi ni mniej ni więcej, o to żeby nie dokładać niepotrzebnych komplikacji do swoich rozwiązań; co sporo ludzi robi.

  1. S mówi: jeśli masz zamiar dołożyć niepotrzebną odpowiedzialność do klasy, don't
  2. O mówi: jeśli masz niepotrzebne zamknąć klasę na rozbudowę, don't
  3. L mówi: jeśli masz niepotrzebne upośledzić dziecko/child jakiejś hierarchi, don't
  4. I mówi: jeśli masz zamiar dodać więcej metod do intefejsu, don't
  5. D mówi: jeśli masz zamiar uzależnić wysokopoziomowy kod od niskopoziomowych szczegółów, don't.

Oczywiście, wszystkie te zasady robi się po to żeby kod był bardziej reużywalny; a nie poprzez dokładanie niepotrzebne reużywalnego wysiłku do kodu; tylko raczej poprzez nie dodawanie niepotrzebnych przeszkadzajek. SOLID, i właściwie wszystkie dobre praktyki i paradgymaty mówią bardziej czego nie robić; anieżeli co robić.

Co innego jest zrobić żeby klasy i funkcje były reużywalne; a co innego jest dokładać więcej wspieranych formatów niż faktycznie potrzebujesz.

SOLID wcale nie mówi "wszystko ma być reusable", takie przekonanie wynika tylko z niezrozumienia idei.

0

@TomRiddle: być może cenna uwaga. Tutaj akurat format pliku jest obojętne. Nie do końca rozumiem to co napisałeś o SOLID :/ To takie ogólniki jak dla mnie, dlatego szukałem jakiś opracować i znalazłem informacje, że każda metoda i klasa powinna być jak najmniej skupiona na danej operacji, a być gotowa do wykonywania również podobnych operacji. Ale może źle to rozumiem. Chętnie posłucham jak ty interpretujesz te zapisy w SOLID.
Druga sprawa, że wciąż nie wiem co z tym plikiem projektu zrobić. W zasadzie w Canvas w Tkinterze można np robić load i save, ale tam w razie czego jest łatwiej, bo Canvas może być pusty. U mnie nie wiem jakby pusty miał działać. Mógłbym zrobić aby save_changes nie robiło po prostu nic jeśli nie wczytamy ani nie stworzymy plików projektu, ale nie wiem też czy to zgodne ze sztuką.

0
iProgramist napisał(a):

@TomRiddle: być może cenna uwaga. Tutaj akurat format pliku jest obojętne. Nie do końca rozumiem to co napisałeś o SOLID :/ To takie ogólniki jak dla mnie, dlatego szukałem jakiś opracować i znalazłem informacje, że każda metoda i klasa powinna być jak najmniej skupiona na danej operacji, a być gotowa do wykonywania również podobnych operacji.

Nie wiem czy to ma sens.

Ale może źle to rozumiem. Chętnie posłucham jak ty interpretujesz te zapisy w SOLID.

No SOLID to jest nic innego jak zbiór 5 zasad. Nie ma innej rady niż nauczyć się każdej z nich z osobna. Ciężko powiedzieć coś o nich łącznie, jedynie można opowiadać o każdej literce osobno.

Druga sprawa, że wciąż nie wiem co z tym plikiem projektu zrobić. W zasadzie w Canvas w Tkinterze można np robić load i save, ale tam w razie czego jest łatwiej, bo Canvas może być pusty. U mnie nie wiem jakby pusty miał działać. Mógłbym zrobić aby save_changes nie robiło po prostu nic jeśli nie wczytamy ani nie stworzymy plików projektu, ale nie wiem też czy to zgodne ze sztuką.

Zrób jakiś POC, spróbuj napisać minimum implementacji i pójdziemy os tego zrób program w którym możesz edytować obrazy, a potem pomyślimy o persystencji, ok?

0

@TomRiddle:
No nie rozumiem tych zasad SOLID. Jakby nie wiem jak ich interpetować, bo mam wrażenie, że same w sobie nic nie mówią.
Nie rozumiem też o czym mówisz do mnie w ostatnim zdaniu :/

0
iProgramist napisał(a):

No nie rozumiem tych zasad SOLID. Jakby nie wiem jak ich interpetować, bo mam wrażenie, że same w sobie nic nie mówią.

Moja osobista interpretacja SOLID to:

  • S, SRP, umiejętność followowania tej zasady wymaga trochę doświadczenia; ale w skrócie chodzi o to że ja klasa zaczyna operować na dwóch poziomach abstrakcji, albo jak jej testy zaczynają się od siebie różnić, tak że widać jakąś granicę pomiędzy klasą; albo kiedy używasz takiej klasy, mimo że tylko część feature'ów ma sens; to jest znak że tak na prawdę w tej jednak klasie ukrywają się dwie klasy połączone w jedną i trzeba je rozdzielić, żeby zachować możliwość późniejszego rozwijania ich niezależnie od siebie. Ale nadal; tu jest mowa o klasa i funkacjach, elementach języka programowania, nie o funkcjonalnościach.
  • O, Open/Close; tutaj chodzi o to, a przynajmniej ja to tak rozumiem, że jeśli dokładasz kilka samopodobych funkcjonalności do istniejącego rozwiązania, np korzystając z polimorifzmu i strategii, to powinieneś tak zaprojektować klasę, żeby klasa używająca nie wiedziała zbyt wiele o implementacji klasy dostarczających; przez co dodanie nowych klas (extension) jest proste i możliwe bez edycji klasy wymagającej (modification). Stąd "otwarty na extension, closed for modification". Ale tej z zasady raczej się korzysta nie za często, bo mało klas spełnia potrzebne kryteria.
  • L, LSP, tam gdzie można użyć rodzica, powinno się móc użyć dziecka; w skrócie. Najprostszy przykład, mówi żę tam gdzie da się użyć float, powinno sie też móc przekazać int. Albo tam gdzie można przekazać Collection, powinno się móc przekazać List<>. Innymi słowy, dzieci rozszerzające nie powinny łamać kontraktu rodziców.
  • I, ISP, niektórzy Ci powiedzą że to znaczy "małe interfejsy są lepsze niż duże", nie do końca się z tym zgadzam. Tutaj chodzi o to, że jeśli masz udostępnić komuś jakiś kontrakt, to zamiast postać jeden duży "General-purpose contract", lepiej stworzyć więcej "specific-purpose contract". Jeśli się da oczywiście; bo istnieją bardzo zwarte kontrakty mające wiele funkcji, także z tym "małe interfejsy" to nie do końca prawda.
  • D, dependency inversion - w dawnych czasach wysokopoziomowe klasy musiały polegać na niskopoziomych szczegółach. Teraz mamy polimorfizm w praktycznie każdym języku, więć to już nie jest konieczność. Teraz można tak zaimplementować całą aplikacje że żaden wysokopoziomowy moduł nie musi zależeć od szczegółów implementacyjnych niżej poziomowych modułów.
iProgramist napisał(a):
TomRiddle napisał(a):

Zrób jakiś POC, spróbuj napisać minimum implementacji i pójdziemy os tego zrób program w którym możesz edytować obrazy, a potem pomyślimy o persystencji, ok?

Nie rozumiem też o czym mówisz do mnie w ostatnim zdaniu :/

Chodzi o to żebyś zrobił jakąś początkową wersję programu i pokazał ją tutaj; i na jej podstawie pójdziemy dalej.

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