Pisanie kodu na wyrost czy spełnianie wyłącznie podanych wymagań ?

0

Witam,
ostatnio w pracy spotyka mnie pewna sytuacja. Tworząc jakieś funkcjonalności szef wymaga ode mnie, abym je szybko programował (co jest zrozumiałe, bo czas to pieniądz). Staram się to robić zgodnie z zasadami SOLID, KISS, DRY, no i ogólnie tak żeby soft był ok i się nie sypał. Następnie w projektach pojawiają się zmiany, które w dużym stopniu wymagają refaktoryzacji obecnego kodu, modyfikacji bazy danych czy innych sporych zmian w logice. Wiąże się to dla mnie z narzutem czasowym, bo nie dość że dochodzą nowe funkcjonalności, to jeszcze trzeba poaktualizować encje w kodzie (czy inne duperele z bazą danych), sprawdzić czy przypadkiem żaden inny fragment kodu się nie posypie itp itd.

Wtedy słyszę komentarz że robię to zbyt wolno i powinienem był przewidzieć różne możliwe warianty i sytuacje - aby od razu napisać kod praktycznie na tyle uniwersalny że można go rozwijać w każdą stronę. Niestety na pisanie testów jednostkowych nie możemy sobie pozwolić, ze względu na brak czasu (zgodnie z zasadą ... po co pisać testy skoro coś działa? :( )

Obecnie staram się pisać kod tak - aby spełniał wymagania co do projektu i nie robił nic ponadto, stąd ten cały temat. A jak to u Was wygląda? Może ktoś zdradzi na pseudo-przykładzie - jak wygląda zmiana dużej funkcjonalności w sofcie?

6

Twoim zadaniem jest pisanie kodu na podstawie aktualnych wytycznych, a nie głowienie się "na co klient może jeszcze wpaść".

3

Ale pisać tak, by jednak rozbudowa nie nastręczała zbyt dużych trudności. Business is business

4
Wielki Szczur Chaosu napisał(a):

https://en.wikipedia.org/wiki/You_aren't_gonna_need_it

  1. Za brak testów tym się właśnie płaci - poświęconym czasem albo bugami później. Jeśli szef tego nie rozumie... zmień szefa. Jest w ogóle "techniczny"?

  2. Jeśli dobrze stosujesz praktyki SOLID rozszerzanie i zmiany funkcjonalności nie powinno być aż tak trudne. Tyle w teorii. Wiem jakie to trudne sam po sobie. Ciągle sam nad tym pracuje. Zmiany jednak mogą być czasochłonne - zmiana encji, bazy, sprawdzenie czy działa od nowa, po migracji, lokalnie, na setupie klienta...
    To też powinno być rozumiane przez szefa. Zresztą pewnie jakbyś za wiele robił od razu, implementował "na zaś" to też o to by był pretensje.

Jeśli u Ciebie zmiany są tak bolesne to popracuj nad SOLID tym bo to ciężki temat w praktyce. Tu jest fajna poczytanka na ten temat, warto sobie przypominać (jak masz inne ciekawe źródła chętnie sam spojrzę):
https://lostechies.com/wp-content/uploads/2011/03/pablos_solid_ebook.pdf

  1. Własne doświadczenia: Nie czułem nigdy presji czasu że coś zajmuje mi zbyt długo. Pracując na spagetti kodzie to że wszystko długo zajmowało było normalne i nikt nie robił afery. Zdawali sobie sprawę jak wygląda smutna rzeczywistość projektu. Pracując na normalnym kodzie też nigdy tego nie odczułem. Jeśli wiele rzeczy trzeba zmienić to trzeba i tyle. W najgorszym wypadku musiałem robić po macoszemu i zaciągać dług techniczny. Ale to też się odbijało później i było wiadomo i usprawiedliwione czemu trzeba teraz czasu na doprowadzenie czegoś do porządku.
0

@AreQrm

  1. Tak właśnie pracuje:)

  2. Szef jest techniczny, ale są to sporadyczne prace - pisanie na szybko jakichś pojedynczych funkcjonalności do obsługi maszyn, co przekłada się na mniejsza skalę projektu. A testy... gdyby nie ja to nikt by o nich w firmie nie słyszał.

  3. No właśnie widzę coraz częściej, że już nawet single responsibility załatwia za mnie sporo tematów.
    A co chodzi o moje źródła to :

  • prezentacje na SlideShare
  • tutki z lynda.com(+podobne serwisy),
  • wykłady z confitury (i innych eventów)
  • http://helion.pl/ksiazki/refuko (to też tylko wierzchołek książkowej góry lodowej :) )
  1. U mnie podobnie.... czyli prostu odczuwam normalny tok pracy :)
4

Gdy ja zaczynałem pracę to czysty kod i dobre praktyki uważałem za coś niezmiernie ważnego, i za wszelką cenę starałem się robić kod jakościowy, kod, który nie będzie gnębił inne osoby. Ponadto czułem, że pisząc kod muszę robić go dobrze, bo w końcu pod tym się podpisuję. Napotykając pierwsze projekty było to dla mnie niepokojące, gdy widziałem jak porąbane systemy (słaby kod, brak testów, problemy z wydajnością) ludzie potrafią pisać.

Z czasem zobaczyłem, że jest to reguła niż wyjątek. Dlatego wiele teorii jaką widzę w książkach nie ma praktycznego odzwierciedlenia w praktyce i osobiście jestem zdania, że dobry programista to właśnie taki, który potrafi połączyć szybkie pisanei słabego kodu z możliwością szybkiego spłacenia długu technicznego (jak tylko pojawi się dużo hajsu i czasu).

Przykład:

Gdybym miał napisać moduł, który mogę dokładnie przetestować jednostkowo, integracyjne i wydajnościową. Z myślą o tym, że mój moduł będzie korzystał z OOP, wzorców projektowych i rozmaitych frameworków, bibliotek to z pewnością potrzebowałbym na to wiele czasu na implementacje, poznanie narzędzi, otrzymam wtedy i tak spóźniony feedback, i jeszcze będę musiał poświęcić też sporo czasu na możliwe przeróbki, poprawki i dopiero wtedy mogę oddać moduł. To to by wyglądało, gdybym miał to robić po bożemu.

Natomiast obecnie robię to tak. Najpierw oceniam wagę modułu, jeśli jest ważny to dam mu tylko parę integracyjnych testów. Jeśli jest średnio ważny dam mu 1 test integracyjny, a jeśli nie wiadomo czy jest ważny wtedy nie dam wcale testów.

Od strony implementacji zadbam tylko o wystawienie interfejsów, odpowiednio powiążę z klasy za pomocą wstrzykiwania zależności, tak by zawsze istniała możliwość napisania testów jednostkowych. Gdy już mam interfejsu to staram się napisać implementację tak szybko jak to możliwe, ale z drugiej strony dbam o podział na metody, odpowiednie nazewnictwo.

Takie podejście coraz częściej u mnie się sprawdza, bo jeśli klient stwierdzi, że potrzebuje czegoś innego to nie leci do kosza wiele poświęconego czasu np. na testy, projektowanie itp Natomiast jeśli klient stwierdzi, że ta funkcjonalność ma być rozbudowana wtedy zawsze istnieje możliwość dostrojenia aplikacji pod kątem implementacji czy dodania testów jednostkowych.

0

A czy w waszych firmach nie po prostu ustalonych standardów jak co się pisze? Wydaje mi się, że m.in. od tego są tacy inżynierowie oprogramowania czy seniorzy, żeby pilnować architektur i tworzyć reguły wytwarzania oprogramowania, żeby nie panowała anarchia i widzimisizm wśród koderów.

7

Czego nauczyłem się w mojej poprzedniej pracy:

  • ważne jest wiedzieć jak pisać poprawny kod
  • ważne jest żeby propagować takie tworzenie kodu
  • ale jeśli nie możesz wymusić odpowiednich standardów, Twój szef patrzy na Ciebie jak na wariata i łapie się za portfel gdy mówisz o długu technicznym, i więcej jest dni gdy rzucasz @!^%!@ zamiast wpadać w zachwyt nad czyimś kodem, to... zmień pracę
3
minus_123456 napisał(a)

osobiście jestem zdania, że dobry programista to właśnie taki, który potrafi połączyć szybkie pisanei słabego kodu z możliwością szybkiego spłacenia długu technicznego

Ja w ten sposób piszę, ale tylko swoje projekty hobbystyczne, które robię sobie samemu (tj. piszę słaby chaotyczny kod, który działa. A potem bardzo szybko potrafię zrefaktoryzować).

Jednak jakoś nie wierzę, że w projekcie rozwijanym przez kilka osób można dalej w ten sposób pisać. Tzn. inaczej - wierzę, bo widziałem takie kody. Tyle, że zwykle był to legacy kod napisany przez osobę X, której często już dawno nie było w projekcie, i która nie podejmie się już sprzątania swojego gówna. Refaktoring legacy projektów pisanych w ten sposób nie jest niczym przyjemnym. Ktoś kiedyś zaciągnął kredyt techniczny - ale teraz to my go musimy spłacać. I nie wiadomo jak się do tego zabrać.

Więc sorry, ale nie. Projekt, przy którym siedzi kilka osób powinien być robiony tak, żeby można było się potem połapać, a nie na szybcika. Jeśli samemu zrobię coś brzydkiego (np. kopiuj-wklej), to w trymiga się później połapię i np. wydzielę metodę żeby uniknąć duplikacji kodu, zajmie mi to kilka minut. Reperowanie kopy-pasty czy innych złych praktych tworzonych przez kogoś innego już nie jest takie wesołe i zajmie mi to np. 2 dni.

Z myślą o tym, że mój moduł będzie korzystał z OOP, wzorców projektowych

ten magiczny narzut czasowy na zaimplementowanie OOP czy wzorce projektowe ma miejsce chyba tylko w Javie, C# czy innych języku statycznie typowanych. W językach dynamicznych to nie problem pisać obiektowo i robić to szybko (języki dynamiczne, super partia, k#@#$! ;) )

Pisząc w JavaScript(przypuszczam, że w Pythonie i Rubym też, chociaż w nich rzadziej piszę) jakoś nie spotkałem się z tym, żeby napisanie czegoś obiektowo zajmowało więcej czasu niż strukturalnie. Implementowanie wzorców projektowych też w JS jest banalne.

Więc: jeśli jest duża presja czasowa i krótki deadline to warto pisać w językach dynamicznych, bo pisze się w nich o wiele szybciej, zachowując dalej zasady OOP i wzorce projektowe. W językach dynamicznych łatwiej zrobić również jakiegoś brzydkiego hacka (jeśli uznamy, że zaciąganie kodu technicznego jest jednak koniecznie), a później łatwiej takiego hacka odkręcić... ;)

Chyba, że też pisałeś w jakimś języku dynamicznym, ale jeśli tak, to nie rozumiem problemu.

0
perotin napisał(a):

A czy w waszych firmach nie po prostu ustalonych standardów jak co się pisze? Wydaje mi się, że m.in. od tego są tacy inżynierowie oprogramowania czy seniorzy, żeby pilnować architektur i tworzyć reguły wytwarzania oprogramowania, żeby nie panowała anarchia i widzimisizm wśród koderów.

No i w efekcie panuje widzimisię seniorów i architektów.

LukeJL napisał(a):

ten magiczny narzut czasowy na zaimplementowanie OOP czy wzorce projektowe ma miejsce chyba tylko w Javie, C# czy innych języku statycznie typowanych. W językach dynamicznych to nie problem pisać obiektowo i robić to szybko (języki dynamiczne, super partia, k#@#$! ;) )

No tak, bo kod w takich dynamicznych cudach techniki jak PHP i JS jest wprost najeżony wzorcami i OOP. ;]

Narzut czasowy potrzebny jest na przemyślenie i wybór drogi, nie na samą implementację - to akurat powinno być oczywiste dla każdego, kto nie jest klepaczem. Zaś wprowadzanie wzorców do legacy codu to bardzo czasochłonna praca, gdyż zazwyczaj trzeba zacząć od napisania testów, których do tej pory nie było. A, że to legacy kod, to i napisanie testów często jest niemożliwe.

Pisząc w JavaScript(przypuszczam, że w Pythonie i Rubym też, chociaż w nich rzadziej piszę) jakoś nie spotkałem się z tym, żeby napisanie czegoś obiektowo zajmowało więcej czasu niż strukturalnie. Implementowanie wzorców projektowych też w JS jest banalne.

Banalne, jeśli się je zna, bo ludzie, którzy znają i rozumieją wzorce, zastosują je bez problemu w dowolnym sensownym języku. Sęk w tym, że większość ludzi zna wzorce jedynie z nazwy, a w praktyce po prostu kopiuje kod zamiast zastanowić się nad tym, jak to zrobić dobrze.

Więc: jeśli jest duża presja czasowa i krótki deadline to warto pisać w językach dynamicznych, bo pisze się w nich o wiele szybciej, zachowując dalej zasady OOP i wzorce projektowe.

No, a do tego nie ma błędów typowania, więc nic się nie wypieprzy przed wdrożeniem, a że użytkownik dostanie jakieś błędy typowania na twarz, to jakie to ma znaczenie. :P

0

Długo pisałem tak jak to sobie kierownicy wymyślali , czyli szybko, bez testów i z pełnym drutowaniem "aby działało" bo to podejście sprawiało, że miałem spokuj, ale jak później trafiłem na utrzymanie pewnego projektu i zobaczyłem ile przez takie podejście jest syfu z którym się musiałem męczyć to zwyczajnie olewałem opierdole, że trzeba szybko i robiłem tak jak trzeba(tzn w miarę rozsądku).

Kłopot był taki, że firma sprzedawała projekt, klient testował z grubsza a później płacił za poprawki w ramach CR więc firma jakość miała gdzieś.
Taki model firmy sprawia tyle, że kod bardzo szybko(a przynajmniej o wiele szybciej) dąży do momentu gdzie utrzymanie się nie opłaca bo kod wygląda jak ... .
Gdyby klient sprawdził projekt porządnie to problemu jakości by nie było, bo błędy byłyby poprawiane za kasę firmy, więc czas na jakość by się znalazła.

2

o, nie zauważyłem tej wypowiedzi wcześniej. cc @somekind

No tak, bo kod w takich dynamicznych cudach techniki jak PHP i JS jest wprost najeżony wzorcami i OOP. ;]

W PHP nie wiem jak jest, bo w nim nie programuję, poza tym nie uważam PHP za dynamiczny język (PHP to takie nie wiadomo co, składnia Perla połączona z obiektówką Javy).

Co do JavaScript to nie rozumiem tego stwierdzenia. Pewnie, że w JS używa się wzorców. Cały Angular na tym bazuje. Chociaż to trochę zły przykład, bo Angular okazał się być wielką pomyłką przez to, że "jest wprost najeżony wzorcami i OOP". Nadmierne napakowanie wzorcami to taki overengineering.

Tym niemniej jak chcesz, to możesz w JS każdy wzorzec zrobić: http://addyosmani.com/resources/essentialjsdesignpatterns/book/

edit:

No, a do tego nie ma błędów typowania, więc nic się nie wypieprzy przed wdrożeniem, a że użytkownik dostanie jakieś błędy typowania na twarz, to jakie to ma znaczenie. :P

można tego uniknąć stosując np. Flow ("Flow is a static type checker, designed to find type errors in JavaScript programs:"), ale ja tego nie stosowałem akurat.

Banalne, jeśli się je zna, bo ludzie, którzy znają i rozumieją wzorce, zastosują je bez problemu w dowolnym sensownym języku. Sęk w tym, że większość ludzi zna wzorce jedynie z nazwy, a w praktyce po prostu kopiuje kod zamiast zastanowić się nad tym, jak to zrobić dobrze.

Po prostu 90% programistów to idioci (bo 90% ludzi ogólnie to idioci, a za programowanie biorą się dzisiaj przypadkowe osoby, więc raczej ciężko oczekiwać czegoś innego).

Narzut czasowy potrzebny jest na przemyślenie i wybór drogi, nie na samą implementację - to akurat powinno być oczywiste dla każdego, kto nie jest klepaczem

No tak, taki narzut faktycznie jest, masz rację.
Z drugiej strony czasem ten narzut jest taki, że myślisz dzień, dwa i więcej nawet, testujesz potencjalne rozwiązania... A czasem wpadasz na coś po minucie. Nie wiem czy obiektówka tu gra rolę. W programowaniu są trudniejsze problemy od obiektówki (np. programując w JavaScripcie dużo czasu trzeba spędzić na obchodzeniu ograniczeń bądź bugów różnych przeglądarek. Ew. na obchodzeniu niedoskonałości CSSa itp. To zabiera tam mnóstwo czasu. Dochodzą też ograniczenia frameworków (np. programując w Angularze czasem trzeba sie głowić jak zrobić coś tak, żeby przechytrzyć Angulara).

A co do samej obiektówki, to i tak nie powinno jej być zbyt dużo, bo to niezdrowo. Wg mnie obiektówka jest dobra jako pewien szkielet aplikacji, a w środku i tak najlepiej pisać funkcyjnie (nie koniecznie wszędzie, ale w tych miejscach które się do tego nadają, programowanie funkcyjne + oop = profit :).

1
LukeJL napisał(a):

W PHP nie wiem jak jest, bo w nim nie programuję, poza tym nie uważam PHP za dynamiczny język (PHP to takie nie wiadomo co, składnia Perla połączona z obiektówką Javy).

Co do JavaScript to nie rozumiem tego stwierdzenia. Pewnie, że w JS używa się wzorców.

PHP to język dynamicznie typowany i tyle, tu nie ma co uważać.
Jeździsz po statycznie typowanych językach, za ich rzekomą trudność, tymczasem w dynamicznych językach mimo ich "łatwości" też powstaje słaby kod. 95% kodu JS na świecie jest oparta o wzorzec copy and paste from StackOverflow, stąd mój sarkazm.

A co do samej obiektówki, to i tak nie powinno jej być zbyt dużo, bo to niezdrowo. Wg mnie obiektówka jest dobra jako pewien szkielet aplikacji, a w środku i tak najlepiej pisać funkcyjnie (nie koniecznie wszędzie, ale w tych miejscach które się do tego nadają, programowanie funkcyjne + oop = profit :).

Nie tyle funkcyjnie, co wystarczy OOP z zachowaniem bezstanowości i niezmienności obiektów.

1

Dla @LukeJL i @somekind mam news - można pisać słabo lub rzetelnie w każdym języku. Widziałem już dobry kod w COBOLu i słaby w Javie.
Dlaczego powstaje słaby kod w dobrym języku OOP - to już było wyżej - krzywa Gausa itd.
Podobnie jest z "overengineering" - można go spotkać wszędzie tam gdzie ważną rolę pełni "job security policy" lub ktoś się po prostu strasznie nudził.

Jeśli chodzi o PHP to słaby kod tam się pojawia nie dlatego że język jest słaby, na wiele pozwala lub też ma śmieszne rozwinięcie nazwy. Pojawia się tam dlatego że nauczenie się PHP-a nie jest czymś trudnym i każdy kto z sukcesem wdrożył WP może myśleć że jest programistą.

To czy kod kieruje się OOP czy bardziej FP albo strukturalny - nie ma znaczenia. Ważne jest żeby w ogóle jakaś myśl przewodnia mu przyświecała - najlepiej łatwo rozpoznawalna lub ew. udokumentowana.

1

Nie tyle funkcyjnie, co wystarczy OOP z zachowaniem bezstanowości i niezmienności obiektów.

Czyli de facto funkcyjnie pod kątem koncepcji. Tak jak można pisać funkcyjnie za pomocą obiektów, jak i można pisać obiektowo z użyciem samych funkcji.

PHP to język dynamicznie typowany i tyle, tu nie ma co uważać.

Nie wiem jak jest teraz, na szczęście w nim już nie programuję. Ale pamiętam, że tam każdy obiekt miał przypisaną swoją klasę i nie można było programować jak w Pythonie (w Pythonie jest duck typing - jeśli obiekt ma metodę "kwacz" to jest kaczką, niezależnie od tego czy jawnie implementuje interfejs czy nie), tylko trzeba było statycznie deklarować wszystkie typy pisząc program. No ale możliwe, że przez ten czas już się zmieniło coś w tym języku.

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