Jak przyspieszyć swoją pracę przy pomocy snippetów?
Widzieliście kiedyś film lub serial przedstawiający programistów? Wszyscy znamy ten obrazek: człowiek, najlepiej w bluzie z kapturem, garbiący się przed komputerem, piszący w tempie, w jakim ludzie nie są w stanie uderzać w klawiaturę, nawet losowo. Setki linii kodu przeskakują przed jego szeroko otwartymi oczami. Nie ma przecież prawa mrugnąć. Chociaż takie tempo nie jest możliwe do osiągnięcia, istnieją sposoby na przyspieszenie naszej pracy. Ten, któremu przyjrzymy się dzisiaj, nazywa się „Snippet”.
Adrian Konkol. Software Developer w Aspire Systems Poland. Od dwóch lat leader koła naukowego „Grupa .NET PG”. Region Leader w programie Microsoft Student Partner oraz główny organizator i prowadzący Hackathonu dla studentów i licealistów „Zombathon”.
Spis treści
Czym są Snippety?
Snippety to małe bloki wstępnie zdefiniowanego kodu, które możemy wstawić do naszego edytora za pomocą prostej kombinacji klawiszy. Microsoft udostępnił nam kilka podstawowych snippetów oraz dał możliwość dodawania własnych. Utworzenie ich jest dość proste i może znacznie przyspieszyć naszą pracę.
Na początek przyjrzyjmy się już przygotowanym snippetom dla .NET Developerów.
Pierwszy z nich jest wykorzystywany do stworzenia konstruktora bez parametrów w naszej klasie. Wywołujemy go słowem „ctor” i dwukrotnym naciśnięciem klawisza Tab.
Większość snippetów jest wywoływana przez akronim bądź krótkie słowo i dwukrotne naciśnięcie klawisza Tab.
Akronimem „cw” wywołujemy najczęściej używaną komendę przy pracy z aplikacją konsolową. Dodaje polecenie:
Console.WriteLine();
Kolejną przydatną rzeczą w snippetach jest to, że pozwalają one otoczyć część naszego kodu predefiniowanym blokiem kodu. Aby to zrobić zaznaczamy linie, które chcemy otoczyć, naciskamy ctrl + k, ctrl + s, a następnie wpisujemy nazwę snippeta lub naciskamy prawy przycisk myszy na podświetlonym tekście i przechodzimy do Snippet -> Surround With.
Stwórzmy nasz pierwszy snippet
Zacznijmy od czegoś prostego: stworzymy snippet do wstawiania DataContextu do naszej klasy.
<?xml version="1.0" encoding="utf-8" ?> <CodeSnippets> <CodeSnippet Format="1.0.0"> <Header> <Title>DataContext</Title> <Shortcut>dc</Shortcut> <Description>Code snippet for DataContext (project specific)</Description> <Author>Adrian Snooking Konkol</Author> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> </Header> <Snippet> <Imports> <Import> <Namespace>Snippets.Data</Namespace> </Import> </Imports> <Code Language="csharp"><![CDATA[private readonly SnippetDataContext _dataContext;$end$]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets>
Przejdźmy teraz do anatomii pliku z rozszerzeniem .snippet:
CodeSnippets to główny element, może zawierać wszystkie snippety, które chcemy dodać, chociaż najlepszą praktyką jest mieć tylko jeden snippet na plik.
Element CodeSnippet definiuje nasz pojedynczy Snippet. Atrybut Format jest wymagany, ale możemy go dowolnie wypełnić. Każdy element CodeSnippet zawiera dwoje dzieci: Header i Snippet.
Header zawiera wszystkie podstawowe informacje o naszym snippecie, takie jak tytuł lub skrót. Tutaj możemy również dodać informacje, jakiego typu jest nasz snippet: w tym przypadku jest to Expansion, co oznacza, że kod można wstawić w miejscu naszego kursora. Możemy również dodać typ SurroundsWith, który pozwoliłby nam otoczyć podświetlony kod, tak jak w przypadku foreach z poprzedniego przykładu.
W elemencie Snippet w końcu implementujemy nasz fragment kodu. Wszystko czego będziemy potrzebowali w naszym snippecie możemy określić tutaj. W tym przypadku użyliśmy elementu Import. Tam możemy zadeklarować wszystkie przestrzenie nazw, tak aby nasz kod był gotowy do użycia od momentu, gdy go wstawimy. Tak samo możemy zrobić z References -> Reference -> Assembly, tak aby wszystkie referencje się zgadzały.
Do omówienia został już tylko element Code. To jedyne dziecko, które jest wymagane dla elementu Snippet. Najpierw musimy dodać atrybut Language, aby nasz edytor wiedział, kiedy szukać tego snippeta. Następnie w <! [CDATA []]> dodajemy kod, którego chcemy użyć z tym snippetem. W powyższym przykładzie jest to: private readonly SnippetDataContext _dataContext; $end$ – gdzie $ end $ to słowo używane do oznaczenia, gdzie powinien znajdować się kursor po dodaniu naszego kodu. Teraz zapiszmy plik z rozszerzeniem snippet i…
To już wszystko! Stworzyliśmy nasz pierwszy Snippet! Teraz zaimportujmy go do Visual Studio. Aby to zrobić, musimy otworzyć Menedżera Snippetów. Możemy to zrobić, klikając Narzędzia -> Menedżer fragmentów kodu… lub skrótem: ctrl + k, ctrl + b.
Teraz musimy kliknąć Importuj, znaleźć właśnie utworzony Snippet, a następnie kliknąć Zakończ.
I voila! Nasz snippet jest gotowy do użycia!
Bardziej zaawansowane snippety
Zobaczmy, co jeszcze możemy zrobić dzięki zastosowaniu Snippetów. Tym razem spróbujemy przygotować żądanie HTTP GET, które wykorzystuje _operationFactory do utworzenia zapytania. Zobaczmy, jak to będzie wyglądać.
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets> <CodeSnippet Format="1.0.0"> <Header> <Title>HttpGet</Title> <Author>Adrian Snooking Konkol</Author> <Description>Adds HttpGet Request prefilled with usual body.</Description> <Shortcut>get</Shortcut> </Header> <Snippet> <Declarations> <Literal> <ID>QueryName</ID> <ToolTip>Replace with proper query.</ToolTip> <Default>IQuery</Default> </Literal> <Literal> <ID>MethodName</ID> <ToolTip>Replace with method name You want to use.</ToolTip> <Default>Name</Default> </Literal> <Object> <ID>Route</ID> <Type>string</Type> <ToolTip>Replace with a proper Route.</ToolTip> <Default>Route</Default> </Object> </Declarations> <Code Language="CSharp"> <![CDATA[[HttpGet, Route($Route$)] public async Task<IActionResult> Get$MethodName$() { var result = await _operationFactory .Create<$QueryName$>($end$) .HandleAsync(); if (!result.HasSucceeded) { return BadRequest(result.Errors); } return Ok(result.Data); }]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets>
Tym razem w elemencie Snippet możemy zobaczyć element Declarations. Tutaj możemy określić elementy Literal i Object:
- Literal – określenie części kodu, która jest w całości w tworzonym Snippecie i którą będziemy zmieniać prawie za każdym razem, gdy używamy Snippeta.
- Object – określenie elementu, który jest używany przez fragment kodu, ale jest zdefiniowany poza nim (np. Jako właściwość wewnątrz klasy).
Zarówno literal, jak i object zawiera elementy ID, tooltip oraz default, chociaż object zawiera dodatkowo element type. Oba mogą również zawierać element Function, ale na potrzeby tego tutorialu pominiemy tę możliwość. Możecie dowiedzieć się więcej na temat Code Snippet Functions – Visual Studio tutaj.
Element ID to nazwa zmiennej, której będziemy używać w naszym szablonie, dodając $ przed i na końcu zmiennej (np. $QueryName$ lub $Route$).
Wartość domyślna to wartość, która zostanie wstawiona do naszego kodu w chwili użycia naszego snippeta.
Po dodaniu odpowiednich elementów literal i object do naszego kodu będziemy mogli przeskakiwać między nimi za pomocą przycisku Tab po użyciu naszego snippeta. W przypadku, gdy nie chcemy zmieniać jednej z wartości, możemy ją pominąć za pomocą przycisku Tab i po naciśnięciu Enter nie będziemy musieli zmieniać żadnych innych wartości (jak pokazano poniżej).
Istnieje również możliwość dodania nowych fragmentów za pomocą Resharper’s Templates Explorer (Extensions -> Resharper -> Tools -> Templates Explorer), ale sprawdzenie tej możliwości pozostawię już Wam.
Podsumowanie
Snippety są jednym z najskuteczniejszych sposobów na przyspieszenie codziennej pracy, a jednak niewielu ludzi stara się je tworzyć. Mam nadzieję, że dzięki temu artykułowi będziecie w stanie błyskawicznie tworzyć własne snippety i przyspieszyć proces kodowania w .NET. I kto wie, być może kiedyś wszyscy będziemy czuć się tak swobodnie z naszym edytorem, jak Jim Carrey.
Jeśli znasz inne zastosowania dla Snippetów – podziel się nimi w komentarzu!
Zdjęcie główne artykułu pochodzi z unsplash.com.