Funkcje C ++ „całego zespołu”?

16

W C ++ funkcje takie jak wyjątki wpływają na cały program: możesz je wyłączyć w całym programie lub musisz postępować z nimi w całym kodzie. W słynnym artykule na temat C ++ Report :

Wbrew intuicji, trudną częścią kodowania wyjątków nie są jawne rzucanie i łapanie. Naprawdę trudną częścią korzystania z wyjątków jest napisanie całego interweniującego kodu w taki sposób, aby arbitralny wyjątek mógł rozprzestrzenić się z jego strony rzutowania do jego programu obsługi, docierając bezpiecznie i bez uszkadzania innych części programu po drodze.

Ponieważ nawet newgeneruje wyjątki, każda funkcja musi zapewniać podstawowe bezpieczeństwo wyjątków - chyba że wywołuje tylko funkcje, które gwarantują brak wyjątku - chyba że całkowicie wyłączysz wyjątki w całym projekcie .

Dlatego wyjątki są funkcją „całego programu” lub „całego zespołu”, ponieważ muszą być zrozumiałe dla każdego w zespole, który ich używa. Ale o ile wiem, nie wszystkie funkcje C ++ są takie.

Możliwym przykładem jest to, że jeśli nie otrzymam szablonów, ale ich nie użyję, nadal będę w stanie napisać poprawne C ++ - czy nie? Mogę nawet przywołać sortszereg liczb całkowitych i cieszyć się niesamowitą przewagą prędkości wrt. C qsort(ponieważ nie jest wywoływany wskaźnik funkcji), bez ryzyka błędów - czy nie? Wygląda na to, że szablony nie są „całym zespołem”.

Czy istnieją inne funkcje C ++, które wpływają na kod, który ich nie używa bezpośrednio, a zatem są „całymi zespołami”? Szczególnie interesują mnie funkcje nieobecne w C.

Aktualizacja : szczególnie szukam funkcji, w których nie ma znaków wymuszonych językowo, o których musisz wiedzieć. Pierwszą odpowiedź, o której wspomniałem, jest ciągła poprawność, która obejmuje również cały zespół, dlatego wszyscy muszą się o tym dowiedzieć; jednak AFAICS wpłynie na ciebie tylko wtedy, gdy wywołasz funkcję, która jest oznaczona const, a kompilator uniemożliwi ci wywoływanie jej na obiektach innych niż const, więc masz coś do znalezienia w Google. Z wyjątkami nawet tego nie rozumiesz; co więcej, są one zawsze używane, gdy tylko z nich skorzystasz new, stąd wyjątki są bardziej „podstępne”. Ponieważ nie mogę tego sformułować jako obiektywnego, docenię każdą funkcję całego zespołu.

Aktualizacja 2 : zamiast funkcji C ++ powinienem napisać coś takiego jak „funkcja specyficzna dla C ++”, aby wykluczyć takie rzeczy, jak wielowątkowość, która dotyczy dużej liczby głównych języków programowania.

Dodatek: Dlaczego to pytanie jest obiektywne (jeśli się zastanawiasz)

C ++ jest złożonym językiem, więc wiele projektów lub przewodników kodowania próbuje wybrać „proste” funkcje C ++, a wiele osób próbuje włączyć lub wykluczyć niektóre z nich w oparciu o głównie subiektywne kryteria. Pytania na ten temat są prawidłowo zamykane tutaj, na SO.

Powyżej natomiast zdefiniowałem (tak dokładnie, jak to możliwe), czym jest funkcja językowa „całego zespołu”, podaję przykład (wyjątki) wraz z obszernymi dowodami w literaturze na temat C ++ i proszę o funkcje całego zespołu w C ++ poza wyjątkami.

To, czy powinieneś użyć funkcji „całego zespołu”, czy też jest to istotna koncepcja, może być subiektywne - ale to oznacza, że ​​jak zawsze znaczenie tego pytania jest subiektywne.

Blaisorblade
źródło

Odpowiedzi:

11

Nominowałbym współbieżność jako funkcję „całego zespołu”.

Chociaż możliwe jest zaprojektowanie oprogramowania w taki sposób, że tylko kilku ekspertów musi mieć świadomość problemów z współbieżnością, a reszta zespołu może czerpać korzyści bez obawy o złożoność (jak w przypadku szablonów), w praktyce robi to nie działa w ten sposób. W praktyce, jeśli masz wiele wątków, musisz dokładnie przeanalizować każdą używaną zmienną, jeśli występują potencjalne problemy z współbieżnością przy takim użyciu.

Bart van Ingen Schenau
źródło
Zgadzam się, że wątki są cechami całego zespołu, chociaż nie są specyficzne dla C ++. Istnieją jednak również inne interfejsy do współbieżności (nie oparte na wątkach), głównie w innych językach, a kilka z nich pozwala na znacznie lepszą enkapsulację współbieżności (choć jest to wciąż aktualny temat badań w językach programowania). Jest więc otwarte pytanie, czy dotyczy to współbieżności per se.
Blaisorblade
@Blaisorblade - C ++ 11 wprowadził własną bibliotekę wątków, więc tak, jest teraz częścią C ++.
Michael Kohne
@MichaelKohne: Nie twierdziłem, że C ++ nie obsługuje wielowątkowości. Powiedziałem, że wątki nie są specyficzne dla C ++, ponieważ ma je wiele innych języków. Właśnie zauważyłem, że opisane problemy dotyczą wątków jako interfejsu do współbieżności.
Blaisorblade,
Powiedziałbym, że „warunek wyścigu” jest lepszym słowem na ten kluczowy problem. Oznacza to, że programiści mogą nie musieć w ogóle pracować lub używać frameworku współbieżności, ale jeśli napiszą dowolny kod C ++, a ich kod może zostać wywołany z więcej niż jednego wątku, wówczas muszą pomyśleć o warunkach wyścigu w ogóle, we wszystkich napisanych kodach.
rwong
Przypomina mi to nieporozumienia ze współpracownikiem, które miały miejsce wiele lat temu. Współpracownik zapytał innego współpracownika: czy to (niektóre funkcje) jest bezpieczne dla wątków? Drugi współpracownik odpowiedział tak. Współpracownik, który następnie poprosił o użycie go z wielu wątków i uzyskał nieoczekiwane wyniki (nie zawiesił się, ale na tym samym obiekcie zastosowano wiele operacji). Okazało się, że współpracownik, który zapytał, nie miał mentalnego modelu tego, co znaczy „bezpieczny dla nici”, i pomylił odpowiedź jako „mogę zrobić, co chcę”.
rwong
10

Oczywistą odpowiedzią jest constpoprawność: ponieważ const/ volatilekwalifikacja jest zaraźliwa, gdy tylko jedna część kodu zacznie go używać, każdy (bezpośrednio lub pośrednio) kod wywołujący musi być również constpoprawny lub constjawnie odrzucać.

Tak jak w przypadku wyjątków, jest to oczywiście dobra rzecz . A nawet bardziej, ponieważ w odróżnieniu od bezpieczeństwa wyjątkowego jest on ściśle weryfikowany przez kompilator.

Konrad Rudolph
źródło
2
Co więcej, const-prawidłowość jest przezroczysta: dotyczy tylko typu , który nadajesz funkcji (która jest zawsze widoczna), a kompilator będzie krzyczeć na ciebie, jeśli się pomylisz. Myślałem o bardziej nieprzejrzystych rzeczach, w których nie masz pojęcia, że ​​coś jest nie tak, dopóki nie będzie za późno (i nawet wtedy trudno będzie to rozgryźć). Ale i tak twoja odpowiedź jest interesująca, dlatego została pozytywnie oceniona.
Blaisorblade
10

Wskaźniki

  • Czy wskaźnik wskazuje pamięć na stosie?
  • Czy wskaźnik wskazuje pamięć na stercie?
  • Czy wskaźnik wskazuje pojedynczy obiekt?
  • Czy wskaźnik wskazuje tablicę?
  • Czy wskaźnik wskazuje lokalizację w środku tablicy?
  • Czy wskaźnik jest prawidłowy?
  • Czy wskaźnik jest zniekształcony?
  • Jaki kod „posiada” wskaźnik?
  • Czy obiekt, do którego istnieje odwołanie, należy ręcznie zwolnić? Jeśli tak to jak?
Thomas Eding
źródło
1
+1 szczególnie ze względu na pytanie o własność wskaźnika. Bez inteligentnych wskaźników własność rozprzestrzenia się naprawdę w całym zespole.
JKor
3

Inną możliwością jest przeciążenie operatora. Raz jedna część kodzie zaczyna majstrować przy przeciążone operatory każdy ma tendencję, aby rozpocząć drugi zgadywania tylko co dokładnie dany obiekt pracują ze jest faktycznie robi. Nie propaguje jawnie przez bazę kodu w sposób, w jaki robią to wyjątki i stała poprawność, ale z pewnością jest to coś, co może zacząć powodować problemy, jeśli cały zespół nie ma na tej samej stronie, kiedy, jak i dlaczego z niego korzystać.

Evicatos
źródło
1

Jedyną poza stałą poprawnością (patrz wyżej), która przychodzi na myśl, jest stan strumieniowania. Jeśli napiszesz kod C ++, w którym korzystasz z obiektów i podobiektów oraz istnieje hierarchia obiektów, ostatecznie będziesz chciał wysłać lub odebrać dane do / od operatora programu. Państwo może napisać proste operacje strumieniowe że będzie skompilować i będzie być semantycznie poprawne ...

std::ostream& operator<< (std::ostream&, MyClass const&) {...}
std::istream& operator>> (std::istream&, MyClass&) {...}

... Ale kiedy to zrobisz, nigdy nie będziesz mieć żadnej gwarancji, że to, co próbujesz napisać (lub, co najważniejsze, przeczytać), ma ten sam format, co klient wysyła. W przypadku strumieni dzieje się zbyt wiele dziwnych przypadków, a nawet gorzej, jeśli musisz przekazywać strumienie lub flagi strumieni jako argumenty w łańcuchu wywołań funkcji… tak jak zwykle przesyłane jest strumieniowanie klas. Tak więc streaming można zdefiniować jako „podstępny”, jak używałeś powyższego terminu, a może nawet jako „wirusowy” ( choć nie w żadnym stopniu w takim samym stopniu, jak stałą poprawności ).

Czy członek głęboko w twojej hierarchii klasowej jest string? Niespodzianka, klient lepiej wysyła jedno słowo, bo inaczej. Masz jakieś liczby, które chcesz serializować? Lepiej sprawdzaj, zapisuj i przywracaj flagi strumieniowe na każdej głębokości wywołania funkcji, ponieważ nigdy nie wiesz, kto jest idiotą, który ustawił swój strumień na ósemkowe wyjście przed wywołaniem twojej funkcji. Albo gorzej - kto właśnie nazwał coś podobnego, setfilla setwtym samym złamał formatowanie wejścia / wyjścia twojego pierwszego - i tylko pierwszego - integralnego elementu, ponieważ te stany nie propagują się . No i nie pytajmy o strumienie i internacjonalizację.

W języku nie ma ostrzeżenia, że ​​przesyłasz strumieniowo w prawidłowy lub niewłaściwy sposób, a nawet w ogóle . Pytanie o kod klienta, który należy przekazać do zapisu kopii zapasowej danych? Tak naprawdę nie masz sposobu, aby wiedzieć, że strumień wskazuje /dev/null. ( Z drugiej strony możesz w ten sposób uzyskać niesamowite prędkości tworzenia kopii zapasowych i współczynniki kompresji! )

Luis Machuca
źródło