Napisy?
Typ string jest jednym z najczęściej używanych typów danych w aplikacji. Gdy go potrzebujemy, to po prostu otwieramy cudzysłów, wpisujemy wartość i zamykamy cudzysłów. Bardzo często nawet nie zastanawiamy się, czy to dobre podejście.
Niestety w dłuższej perspektywie takie podejście oznacza problemy. A to podczas pobierania wartości ze słownika robimy w kluczu literówkę, o której dowiadujemy się dopiero podczas wykonywania kodu (o ile go przetestujemy). A to musimy w 20 miejscach poprawić komunikat wyświetlany użytkownikowi, a nie zawsze CTRL + H to dobre rozwiązanie.
Dlatego warto się na chwilę zatrzymać i zastanowić, czy nie można zrobić tego lepiej.
Rodzaje napisów w aplikacji
Na przestrzeni lat zauważyłem, że napisy w aplikacji możemy podzielić na dwa rodzaje:
- wewnętrzne aplikacji – używane tylko w kodzie, na przykład nazwa ustawienia, klucz do słownika itp.
- wyświetlane użytkownikowi w interfejsie aplikacji.
Znając już rodzaje napisów w aplikacji, możemy dla każdego z nich przygotować mechanizm, który ułatwi pracę z nimi.
Napisy wewnętrzne aplikacji
Do stringów tego rodzaju wykorzystuję klasy ze stałymi. Napisy grupuję według użycia i dodaję je do dedykowanych klas. Na przykład nazwy ustawień z pliku konfiguracyjnego będą znajdować się w klasie SettingsNames:
public static class SettingsNames | |
{ | |
public const string ApplicationName = "ApplicationName"; | |
} |
Później korzystam z tych stałych w aplikacji. Dzięki temu unikam wszelkiego rodzaju literówek, bo w każdym miejscu używam tej samej wartości. Dodatkowo intellisense podpowiada dostępne wartości, co również jest bardzo pomocne:
//użycie bezpośrednie napisu | |
var applicationName = ConfigurationManager.AppSettings["ApplicationName"]; | |
//skorzystanie z stałej | |
var applicationName = ConfigurationManager.AppSettings[SettingsNames.ApplicationName]; |
Na ogół używam stałych (słowo kluczowe const w C#), ale czasami to nie wystarcza. Przykładowo WPF nie umożliwia bindowania do stałej, dlatego czasami korzystam z klas z polami statycznymi typu readonly, ale to są pojedyncze przypadki i na ogół w WPF:
//Nazwy regionów używanych w Prism w aplikacji WPF | |
public static class RegionNames | |
{ | |
public static readonly string Main = "Main"; | |
public static readonly string Menu = "Menu"; | |
public static readonly string StatusBar = "StatusBar"; | |
} |
Napisy wyświetlane użytkownikowi
Drugim rodzajem stringów używanych w aplikacji są napisy wyświetlane w interfejsie użytkownika (czy też innych miejscach, np. w wygenerowanym dokumencie). Do nich wykorzystuję pliki resource’ów. Dzięki temu również na poziomie kodu mam napisy pogrupowane w klasy, podpowiedzi intelisense oraz dodatkowo z czasem mogę zdecydować się na tłumaczenie aplikacji na inne języki.
var applicationName = ConfigurationManager.AppSettings[SettingsNames.ApplicationName]; | |
var message = string.Format(ApplicationResources.HelloMessage, applicationName); | |
Console.WriteLine(message); |
A w jaki sposób organizować napisy w resource’ach? Widziałem różne sposoby. Niektórzy mają jeden duży plik, w którym znajdują się wszystkie napisy. Inni tworzą plik per moduły. Na przykład jeden dla użytkowników, drugi dla produktów i tak dalej. Myślę, że nie ma jednego idealnego sposobu i wszystko zależy od aplikacji, którą tworzymy.
Osobiście najczęściej tworzę pliki resource per plik widoku. Nie ma tutaj znaczenia, czy to jest cały widok, czy tylko jakaś kontrolka osadzana w innym widoku. Dodatkowo mam jeszcze pliki globalne, dla całej aplikacji oraz dla poszczególnych modułów, w których wrzucam często używane napisy.
U mnie takie podejście sprawdza się w aplikacjach, ale niestety musimy się nastawić, że z czasem, gdy będziemy tłumaczyć aplikacje, będziemy musieli nieco zmienić pliki resource’ów. Może się okazać, że w jednym z widoków, z racji braku miejsca, chcemy inaczej przetłumaczyć globalny napis. Przestajemy więc korzystać w tym miejscu z globalnego resource’a, a wpis dodajemy w dedykowanym dla danego widoku resource’u.
Dodatkowo mam jeszcze pliki resource’ów dla niektórych klas w aplikacji. Są to głównie klasy logiki biznesowej, w których znajdują się komunikaty, np. błędy walidacji czy inne informacje.
Osobiście do logów korzystam też z plików resource’ów. Są to dedykowane pliki, które później na ogół nie są tłumaczone i są tylko w języku angielskim lub polskim.
Przykład
Tym razem przykład (https://github.com/danielplawgo/WorkingWithStrings) jest bardzo prosty. Jest to prosta aplikacja konsolowa, która wyciąga wartość z app settings (tak, wiem, jest jeszcze drugi mechanizm, który generuje ładne silnie typowane klasy) i wyświetla komunikat użytkownikowi z pliku resource. Po pobraniu przykładu wystarczy go uruchomić. Nie jest potrzebna dodatkowa konfiguracja.
Podsumowanie
Jak pokazuje życie, warto zastanowić się nad tym, w jaki sposób organizujemy używanie napisów w aplikacji. Za każdym razem, gdy potrzebuję dodać nowego stringa, zastanawiam się, do jakiej kategorii należy. Następnie tworzę nową stałą lub nowy wpis w pliku resource. Narzut na tę dodatkową pracę nie jest zbyt duży, szczególnie że szukanie literówki w pobieraniu jakichś danych może zająć dużo więcej czasu.
A jak Ty organizujesz używanie napisów w aplikacji?
1 thought on “Używanie napisów w aplikacji”