Jestem nieco nowy w programowaniu (z zawodu jestem inżynierem mechanikiem) i podczas mojego przestoju opracowuję mały program, który generuje część (solidworks) na podstawie danych wejściowych od różnych osób z całego zakładu.
Opierając się tylko na kilku danych wejściowych (dokładnie 6), muszę wykonać setki wywołań API, z których każde może zająć nawet kilkanaście parametrów; wszystko wygenerowane przez zestaw reguł, które zebrałem po przeprowadzeniu wywiadu ze wszystkimi, którzy zajmują się tą częścią. Sekcja zasad i parametrów mojego kodu ma 250 linii i rośnie.
Więc jaki jest najlepszy sposób, aby mój kod był czytelny i zarządzalny? Jak podzielić na segmenty wszystkie moje magiczne liczby, wszystkie reguły, algorytmy i części proceduralne kodu? Jak radzić sobie z bardzo szczegółowym i szczegółowym interfejsem API?
Moim głównym celem jest przekazanie komuś mojego źródła i zrozumienie, co robię, bez mojego wkładu.
źródło
Odpowiedzi:
Na podstawie tego, co opisujesz, prawdopodobnie będziesz chciał odkryć wspaniały świat baz danych. Wygląda na to, że wiele magicznych liczb, które opisujesz - szczególnie jeśli są zależne od części - to tak naprawdę dane, a nie kod. Będziesz miał znacznie więcej szczęścia i znacznie łatwiej będzie ci rozszerzyć aplikację na dłuższą metę, jeśli możesz kategoryzować związek danych z częściami i zdefiniować dla niej strukturę bazy danych.
Pamiętaj, że „bazy danych” niekoniecznie oznaczają MySQL lub MS-SQL. Sposób przechowywania danych będzie w dużej mierze zależeć od sposobu korzystania z programu, sposobu pisania itp. Może to oznaczać bazę danych typu SQL lub po prostu sformatowany plik tekstowy.
źródło
O ile nie spodziewacie się rozszerzenia tego na wiele części, nie chciałbym jeszcze dodawać bazy danych. Posiadanie bazy danych oznacza duży zbiór rzeczy do nauczenia się dla ciebie i więcej rzeczy do zainstalowania, aby działały dla innych osób. Dodanie wbudowanej bazy danych sprawia, że końcowy plik wykonywalny jest przenośny, ale osoba z twoim kodem źródłowym ma teraz jeszcze jedną rzecz do zrobienia.
Myślę, że lista wyraźnie nazwanych stałych i funkcji implementujących reguły bardzo pomoże. Jeśli nadasz wszystkim naturalne nazwy i skupisz się na umiejętnościach programowania , powinieneś być w stanie stworzyć czytelny program.
Idealnie byłoby skończyć z kodem, który mówi:
W zależności od tego, jak lokalne są stałe, kusiłoby mnie, aby zadeklarować je w funkcjach, w których są używane, tam gdzie to możliwe. Przydatne jest włączenie:
w
Daje to w dużej mierze samokontrujący się kod, a także zachęca każdego, kto modyfikuje kod, do nadawania podobnie znaczących nazw dodawanym przez siebie treściom. Uruchomienie lokalne ułatwia także radzenie sobie z całkowitą liczbą stałych, które zgromadzisz. To staje się trochę denerwujące, jeśli musisz przewijać długą listę stałych, aby upewnić się, że wartość jest tą, którą chcesz.
Jedna wskazówka dla imion: umieść najważniejsze słowo po lewej stronie. Może nie jest tak dobrze czytany, ale ułatwia znajdowanie rzeczy. Przez większość czasu patrzysz na miskę i zastanawiasz się nad śrubą, nie patrzysz na śrubę i zastanawiasz się, gdzie ona jest, więc nazwij to SumpBoltThreadPitch, a nie BoltThreadPitchSump. Następnie posortuj listę stałych. Później, aby wyodrębnić wszystkie skoki wątków, możesz uzyskać listę w edytorze tekstu i albo użyć funkcji find, albo użyć narzędzia takiego jak grep, aby zwrócić tylko linie zawierające „ThreadPitch”.
źródło
.CreateLine(m_trunion_support_spacing / 2, -((m_flask_length / 2) + m_sand_ledge_width + m_wall_thickness), -m_flange_thickness, m_trunion_support_spacing / 2, -((m_flask_length / 2) + m_sand_ledge_width + m_wall_thickness), -m_flask_height + m_flange_thickness)
createGroove(length, depth)
. Musisz zaimplementować funkcje opisujące to, co chcesz osiągnąć, tak jak opisałbyś je inżynierowi mechanicznemu. Na tym właśnie polega umiejętność programowania.Myślę, że twoje pytanie ogranicza się do: jak ustrukturyzować obliczenia? Zauważ, że chcesz zarządzać „zestawem reguł”, którymi są kod, oraz „zestawem magicznych liczb”, które są danymi. (Możesz zobaczyć je jako „dane osadzone w kodzie”, ale mimo to są danymi).
Co więcej, uczynienie twojego kodu „zrozumiałym dla innych” jest w rzeczywistości ogólnym celem wszystkich paradygmatów programowania (patrz np. „ Wzorce implementacji ” Kent Beck lub „ Clean Code ” Roberta C. Martina dla autorów oprogramowania, którzy mają ten sam cel jak ty, dla dowolnego programu).
Wszystkie wskazówki zawarte w tych książkach dotyczą twojego pytania. Pozwól mi wyciągnąć kilka wskazówek dotyczących „magicznych liczb” i „zbiorów reguł”:
Użyj nazwanych stałych i wyliczeń, aby zastąpić magiczne liczby
Przykład stałych :
należy zastąpić nazwaną stałą, aby żadne późniejsze zmiany nie mogły wprowadzić literówki i zepsuć kod, np. poprzez zmianę pierwszego,
0.625
ale nie drugiego.Przykład wyliczeń :
Wyliczenia mogą pomóc ci zebrać dane, które do siebie należą. Jeśli używasz Java, pamiętaj, że Enums są obiektami; ich elementy mogą przechowywać dane i można zdefiniować metody zwracające wszystkie elementy lub sprawdzić niektóre właściwości. Tutaj Enum jest używane do budowy innego Enum:
Zaletą jest to, że teraz nikt nie może błędnie zdefiniować części silnika, która nie jest wykonana ze stali lub węgla, i nikt nie może wprowadzić elementu silnika o nazwie „asdfasdf”, tak jak byłoby w przypadku, gdyby był to ciąg znaków sprawdzany pod kątem zawartości.
Wzór Strategia i metody wzorca Fabryka opisać jak hermetyzacji „zasady” i przekazać je do innego obiektu, który korzysta z nich (w przypadku wzorca Factory wykorzystanie jest coś budowę, w przypadku wzoru strategią, użycie jest czymkolwiek chcesz).
Przykład wzorca metody fabrycznej :
Wyobraź sobie, że masz dwa typy silników: jeden, w którym każda część musi być połączona ze sprężarką, i jeden, w którym każdą część można dowolnie połączyć z dowolnymi innymi częściami. Zaadaptowano z Wikipedii
A potem w innej klasie:
Interesująca część: teraz Twój konstruktor AssemblyLine jest oddzielony od obsługiwanego typu silnika. Może
addEngine
metody wywołują zdalny interfejs API ...Przykład wzorca strategii :
Wzorzec strategii opisuje, jak wprowadzić funkcję do obiektu w celu zmiany jego zachowania. Wyobraźmy sobie, że czasami chcesz wypolerować część, czasem chcesz ją pomalować, a domyślnie chcesz sprawdzić jej jakość. To jest przykład Pythona, zaadaptowany z Stack Overflow
Możesz rozwinąć tę funkcję, trzymając listę Akcji, które chcesz wykonać, a następnie wywołując je kolejno z
execute
metody. Może to uogólnienie można lepiej opisać jako wzorzec Konstruktora , ale hej, nie chcemy być wybredni, prawda? :)źródło
Możesz użyć silnika reguł. Mechanizm reguł zapewnia DSL (język specyficzny dla domeny), który został zaprojektowany do modelowania kryteriów niezbędnych do określonego wyniku w zrozumiały sposób, jak wyjaśniono w tym pytaniu .
W zależności od implementacji silnika reguł reguły można nawet zmienić bez ponownej kompilacji kodu. A ponieważ reguły są napisane w ich własnym, prostym języku, mogą być zmieniane również przez użytkowników.
Jeśli masz szczęście, istnieje gotowy do użycia silnik reguł dla używanego języka programowania.
Minusem jest to, że musisz zapoznać się z silnikiem reguł, co może być trudne, jeśli jesteś początkującym programistą.
źródło
Moje rozwiązanie tego problemu jest całkiem inne: warstwy, ustawienia i LOP.
Najpierw zawiń interfejs API w warstwie. Znajdź sekwencje wywołań API, które są używane razem i połącz je we własne wywołania API. W końcu nie powinno być żadnych bezpośrednich połączeń z bazowym interfejsem API, tylko połączenia z opakowaniami. Połączenia otoki powinny zacząć wyglądać jak mini-język.
Po drugie, zaimplementuj „menedżera ustawień”. Jest to sposób na dynamiczne kojarzenie nazw z wartościami. Coś takiego. Kolejny mini język.
Na koniec zaimplementuj swój własny mini język do wyrażania projektów (jest to programowanie zorientowane na język). Ten język powinien być zrozumiały dla inżynierów i projektantów, którzy wprowadzają zasady i ustawienia. Pierwszym przykładem takiego produktu, który przychodzi na myśl, jest Gnuplot, ale jest wiele innych. Możesz użyć Pythona, chociaż osobiście nie zrobiłbym tego.
Rozumiem, że jest to złożone podejście i może być przesadą w rozwiązywaniu problemów lub wymaganiem umiejętności, które musisz jeszcze zdobyć. Właśnie tak bym to zrobił.
źródło
Nie jestem pewien, czy poprawnie otrzymałem pytanie, ale wygląda na to, że powinieneś pogrupować rzeczy w niektórych strukturach. Powiedz, jeśli używasz C ++, możesz zdefiniować takie rzeczy jak:
Możesz je utworzyć na początku programu:
Wtedy będą wyglądały twoje wywołania API (zakładając, że nie możesz zmienić podpisu):
Jeśli możesz zmienić podpis API, możesz przekazać całą strukturę:
Możesz również pogrupować wszystkie parametry w większe opakowanie:
źródło
Dziwi mnie, że nikt inny nie wspomniał o tym ...
Powiedziałeś:
Powiem więc tak, większość innych odpowiedzi jest na dobrej drodze. Zdecydowanie uważam, że bazy danych mogą ci pomóc. Ale kolejną rzeczą, która ci pomoże, jest komentowanie, dobre nazwy zmiennych oraz właściwa organizacja / separacja problemów.
Wszystkie pozostałe odpowiedzi są w dużej mierze oparte na zagadnieniach technicznych, ale ignorują podstawy, których uczy większość programistów. Ponieważ jesteś mechanikiem z zawodu, zgaduję, że nie jesteś przyzwyczajony do tego stylu dokumentacji.
Komentowanie i wybór dobrych, zwięzłych nazw zmiennych ogromnie pomaga w czytelności. Co jest łatwiejsze do zrozumienia?
Lub:
To jest dość niezależne od języka. Bez względu na platformę, IDE, język itp., Właściwa dokumentacja jest najczystszym i najłatwiejszym sposobem na upewnienie się, że ktoś zrozumie Twój kod.
Następnie poradzę sobie z zarządzaniem tymi magicznymi liczbami i mnóstwem obaw, ale myślę, że komentarz GrandmasterB poradził sobie z tym całkiem nieźle.
źródło