Visual Studio oferuje wiele narzędzi, które umożliwiają tworzenie nowoczesnych aplikacji chmurowych, w tym .NET Aspire. Aby zacząć, należy utworzyć nowy projekt z szablonu .NET Aspire Starter Application. Projekt można nazwać np. SampleAspireProject. Po utworzeniu projektu, Visual Studio wyświetli stronę przeglądu, zawierającą odnośniki do dokumentacji Microsoftu dotyczącej budowania i wdrażania aplikacji, a także odkrywania usług.

Na tej samej stronie dostępne są również inne zakładki, w tym "Connected Services". Klikając na tę opcję, możemy dodać zależności usług i referencje do usług. Dodanie zależności usług umożliwia wybranie odpowiedniej usługi Azure, którą chcemy dodać do naszego rozwiązania. Ważne jest, aby posiadać aktywną subskrypcję Azure, aby móc pomyślnie zakończyć ten proces.

Klikając na link "Add a service reference", mamy możliwość wyboru między trzema specyfikacjami API: OpenAPI, gRPC oraz WCF Web Service. Dzięki tym narzędziom możemy dodać zależności i zintegrować nasze aplikacje z różnymi usługami chmurowymi.

Szablon, którego używamy, tworzy cztery projekty w ramach naszego rozwiązania:

  • ApiService: minimalne API w ASP.NET Core, pełniące rolę backendowej warstwy logiki.

  • AppHost: projekt, który hostuje konfigurację rozwiązania.

  • ServiceDefaults: projekt zawierający domyślne konfiguracje i obiekty wspólne dla wielu usług.

  • Web: projekt Blazor dedykowany do tworzenia frontendów.

Domyślnie projekt AppHost jest ustawiony jako projekt startowy. Po uruchomieniu rozwiązania, .NET Aspire otworzy okno dashboardu aplikacji SampleAspireApp, które dostarcza ważnych informacji na temat rozwiązania, takich jak logi, ślady oraz konfiguracje środowiska. W panelu "Resources" można uzyskać dostęp do każdego punktu końcowego aplikacji.

Po zakończeniu lokalnego rozwoju naszej aplikacji chmurowej, możemy bezpośrednio opublikować ją na platformie Azure. Należy pamiętać, że aby to zrobić, musimy zainstalować Azure Developer CLI. Aby utworzyć profil publikacji, wystarczy ponownie otworzyć okno przeglądu (Project | Overview).

Rozwój Azure Functions w Visual Studio

Azure Functions to jedno z najpopularniejszych narzędzi w chmurowej ofercie Microsoftu. Jest to usługa obliczeniowa typu serverless, która pozwala na uruchamianie małych fragmentów kodu bez konieczności zarządzania infrastrukturą. Usługa ta reaguje na zdarzenia pochodzące z różnych źródeł, takich jak żądania HTTP, timery, zmiany w bazach danych oraz inne usługi Azure. Dzięki temu możliwe jest tworzenie aplikacji, które reagują na zmiany danych w czasie rzeczywistym, automatyzują zadania i integrują się z innymi systemami.

Aby rozpocząć, należy upewnić się, że na naszej instancji Visual Studio jest zainstalowany zestaw narzędzi dla deweloperów Azure. Można to zrobić w Visual Studio Installer, wybierając odpowiednią opcję.

Po zainstalowaniu zestawu narzędzi, możemy stworzyć nowy projekt Azure Functions, który w tym przykładzie nazwijmy SampleAzureFunction. Następnie Visual Studio poprowadzi nas przez okno, w którym musimy skonfigurować rodzaj wyzwalacza (trigger) i poziom autoryzacji dla funkcji.

Rodzaje wyzwalaczy w Azure Functions

Azure Functions oferuje szeroką gamę wyzwalaczy, które umożliwiają reakcję na różne zdarzenia. Oto niektóre z nich:

  • Http trigger: Tworzy punkt końcowy HTTP, który może zostać wywołany, aby uruchomić funkcję. Jest to przydatne w przypadku tworzenia interfejsów API RESTful.

  • Http trigger z OpenAPI: Jest podobny do wyzwalacza HTTP, ale zawiera wbudowaną obsługę OpenAPI (dawniej Swagger), co ułatwia projektowanie i dokumentowanie API.

  • IoT Hub trigger: Umożliwia funkcjom reagowanie na zdarzenia wysyłane do strumienia zdarzeń z IoT Hub, co jest przydatne do przetwarzania danych telemetrycznych z urządzeń IoT.

  • Kafka trigger: Odbiera wiadomości z tematu Kafka, co jest użyteczne przy przetwarzaniu wiadomości w strumieniu.

  • Queue trigger: Uruchamia funkcję, gdy do kolejki w Azure Queue Storage dodana zostaje nowa wiadomość.

  • SignalR: Umożliwia tworzenie aplikacji do komunikacji w czasie rzeczywistym w środowisku serverless, co jest idealne w przypadku aplikacji wymagających aktualizacji w czasie rzeczywistym.

Po wybraniu odpowiedniego wyzwalacza, należy zdecydować, jaki poziom autoryzacji będzie obowiązywał dla funkcji. Dostępne są trzy opcje:

  • Function: Ogranicza dostęp tylko do użytkowników, którzy mają przyznane odpowiednie uprawnienia do wywołania funkcji.

  • Anonymous: Umożliwia dostęp do funkcji każdemu użytkownikowi, niezależnie od autentykacji. Jest to przydatne w przypadku publicznych API.

  • Admin: Nadaje pełne uprawnienia administracyjne, pozwalając na wykonywanie działań w imieniu użytkownika z pełnymi uprawnieniami.

Publikacja funkcji w chmurze Azure

Po zakończeniu programowania funkcji, możemy ją opublikować w chmurze Azure. Aby to zrobić, wystarczy kliknąć prawym przyciskiem myszy na projekt w Solution Explorer i wybrać opcję "Publish". Następnie wybieramy Azure jako cel publikacji i określamy, że chcemy opublikować naszą aplikację jako Azure Function App.

Ważne jest, aby nadać unikalną nazwę naszej aplikacji funkcji, aby uniknąć konfliktów z innymi aplikacjami w chmurze.

Po pomyślnym opublikowaniu funkcji, będziemy mieć gotową, działającą aplikację serverless w środowisku Azure, która może reagować na różne zdarzenia w czasie rzeczywistym.


Zrozumienie tego procesu pozwala na tworzenie wydajnych i skalowalnych aplikacji chmurowych, które w prosty sposób integrują się z szeroką gamą usług i platform. Aby skutecznie wdrożyć takie aplikacje, warto pamiętać o znaczeniu konfiguracji środowiska, zarządzania zależnościami usług i odpowiedniego dobrania wyzwalaczy, które najlepiej odpowiadają na potrzeby konkretnego projektu.

Jak tworzyć własne szablony projektów w Visual Studio 2022?

Tworzenie własnych szablonów projektów w Visual Studio 2022 pozwala zaoszczędzić czas i zwiększyć produktywność, zapewniając jednocześnie spójność w wielu projektach. Dzięki tej funkcji możemy zdefiniować strukturę i konfigurację nowego projektu, dostosowując go do indywidualnych potrzeb. W tym rozdziale omówimy, jak krok po kroku stworzyć prosty szablon projektu, który zawiera różne pliki, takie jak klasy, pliki konfiguracyjne czy metadane.

Pierwszym krokiem w tworzeniu szablonu jest przygotowanie odpowiednich plików. Na początek należy stworzyć plik klasy w języku C# o nazwie Class1.cs, który będzie częścią szablonu. W tym pliku będziemy wykorzystywać zarezerwowane parametry, takie jak $safeprojectname$ i $year$, które pozwolą na dynamiczne generowanie przestrzeni nazw oraz dodanie informacji o prawach autorskich. Przykład kodu, który można umieścić w tym pliku, wygląda następująco:

csharp
using System;
namespace $safeprojectname$ { /// <summary> /// Represents a simple class in the $safeprojectname$ project. /// Copyright (c) $year$ by Company name /// </summary> public class Class1 { public Class1() { Console.WriteLine("Hello from $safeprojectname$!"); } } }

Po utworzeniu tego pliku, warto również stworzyć plik AssemblyInfo.cs w folderze Properties. Ten plik zawiera metadane o zestawie, takie jak tytuł projektu, firma czy informacja o prawach autorskich. Warto pamiętać, że także tutaj będziemy używać zarezerwowanych parametrów, takich jak $projectname$, $year$ oraz $username$, które zostaną automatycznie zastąpione odpowiednimi wartościami w czasie tworzenia projektu z szablonu. Przykładowy kod:

csharp
using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("$projectname$")] [assembly: AssemblyDescription("A simple class library project.")] [assembly: AssemblyCompany("Your Company")] [assembly: AssemblyProduct("$projectname$")] [assembly: AssemblyCopyright("Copyright © $year$ $username$. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyVersion("1.0.*")]

Kiedy pliki są już gotowe, należy je spakować do pliku .zip i umieścić w katalogu szablonów Visual Studio lub zaimportować je przez menedżera szablonów w Visual Studio. W momencie, gdy użytkownik tworzy nowy projekt na podstawie tego szablonu, Visual Studio poprosi go o nazwę projektu i lokalizację, a wartości zarezerwowanych parametrów, takich jak $safeprojectname$ czy $year$, zostaną automatycznie podstawione.

Po zdefiniowaniu podstawowego szablonu projektu, możemy również dodać tagi, które umożliwią filtrowanie szablonów. W pliku .vstemplate można określić tagi takie jak Language, Platform oraz ProjectType, które ułatwią użytkownikom wybór odpowiedniego szablonu podczas tworzenia nowego projektu. Przykład definicji tagów:

xml
<Tags> <Tag>C#</Tag> <Tag>Windows</Tag> <Tag>Class Library</Tag> </Tags>

Warto również wiedzieć, że Visual Studio pozwala na bardziej zaawansowane konfiguracje, jak tworzenie szablonów wieloprojektowych. Często w większych projektach może być konieczne, aby nowo tworzona aplikacja zawierała kilka różnych bibliotek, co pozwala na tworzenie rozwiązania o czystej architekturze. Aby to osiągnąć, należy połączyć kilka indywidualnych szablonów projektów w jeden szablon rozwiązania, który automatycznie utworzy wszystkie wymagane projekty podczas tworzenia nowego rozwiązania.

Pierwszym krokiem w tym procesie jest przygotowanie szablonów poszczególnych projektów, a następnie stworzenie struktury folderów dla szablonu rozwiązania. Każdy z projektów należy spakować do osobnego folderu i dodać do katalogu szablonów rozwiązania. Następnie, w pliku .vstemplate głównego katalogu rozwiązania, należy zdefiniować strukturę szablonu rozwiązania, wskazując poszczególne szablony projektów. Przykład:

xml
<ProjectTemplateFile Link="Dummy/MyTemplate.vstemplate"/>
<ProjectTemplateFile Link="Application/MyTemplate.vstemplate"/> <ProjectTemplateFile Link="Models/MyTemplate.vstemplate"/>

Po skonfigurowaniu szablonu rozwiązania, całą strukturę należy zapisać w formie pliku .zip i umieścić w odpowiednim katalogu szablonów Visual Studio. Po zaimportowaniu szablonu, użytkownik będzie mógł stworzyć nowe rozwiązanie z wieloma projektami, co znacznie przyspieszy proces konfiguracji projektu.

Zaletą korzystania z własnych szablonów projektów jest nie tylko oszczędność czasu, ale także spójność w organizacji kodu. Dzięki szablonom każdy nowy projekt będzie miał dokładnie tę samą strukturę i konfigurację, co pozwala na łatwiejsze utrzymanie i rozwój aplikacji. Warto również pamiętać, że w zależności od potrzeb, szablony mogą być rozbudowywane o dodatkowe pliki, konfiguracje i zależności, co umożliwia jeszcze większą automatyzację procesu tworzenia nowych projektów.

Jak Test-Driven Development (TDD) poprawia jakość oprogramowania?

Test-Driven Development (TDD) to podejście, które łączy projektowanie, rozwój i testowanie w jedną spójną metodologię, oferując programistom kompleksowe narzędzie do tworzenia prostego, czystego kodu oraz zapewniania jego dokładnych testów. TDD opiera się na prostym cyklu "czerwony-zielony-refaktoryzacja", który wprowadza systematyczne testowanie każdego aspektu logiki biznesowej. Dzięki temu podejściu, które stało się standardem w tworzeniu oprogramowania wysokiej jakości, uzyskuje się najlepsze praktyki kodowania i projektowania na każdym etapie cyklu życia oprogramowania.

Celem TDD jest osiągnięcie prostszego i bardziej niezawodnego kodu. Proces ten, choć jest prosty, ma głęboki wpływ na sposób, w jaki rozwija się oprogramowanie. Rozpoczynając od testu, który nie przechodzi, przez minimalne wprowadzenie kodu w fazie zielonej, aż po refaktoryzację, programiści tworzą kod, który nie tylko spełnia wymagania funkcjonalne, ale również jest łatwy w utrzymaniu i rozwijaniu.

Pierwszą fazą cyklu TDD jest faza "czerwona", w której programista pisze test, który z założenia musi nie przejść, ponieważ nie istnieje jeszcze odpowiednia funkcjonalność w kodzie. Test ten ma na celu określenie oczekiwanego zachowania systemu w kontekście nowej funkcji. Pisanie testu przed implementacją nie tylko pozwala na jasne określenie celów, ale również ułatwia zrozumienie problemu, który ma zostać rozwiązany.

Kolejnym krokiem jest faza "zielona", w której programista pisze minimalną ilość kodu potrzebną do przejścia testu. Kluczowym celem jest tu prostota rozwiązania. Kod nie musi być skomplikowany, ma po prostu rozwiązać problem w sposób najprostszy z możliwych, bez zbędnych komplikacji. Efektem tej fazy jest działający kod, który spełnia wymagania testu.

Po przejściu testu przychodzi faza "refaktoryzacji". W tej fazie programista optymalizuje kod, nie zmieniając jego funkcjonalności. Refaktoryzacja polega na poprawieniu struktury kodu, eliminacji redundancji, poprawie nazw zmiennych i stosowaniu wzorców projektowych, co ma na celu zwiększenie jego czytelności, utrzymywalności i elastyczności w przyszłości. To krok, który pozwala na uporządkowanie kodu, by był bardziej odporny na zmiany i łatwiejszy w utrzymaniu.

Cykl "czerwony-zielony-refaktoryzacja" jest powtarzany iteracyjnie dla każdej nowej funkcjonalności. Powtarzanie tego procesu pozwala na systematyczne i stopniowe rozwijanie bazy kodu, co zapewnia, że oprogramowanie jest stale testowane i dostosowywane do zmieniających się wymagań. TDD, dzięki swojej iteracyjnej naturze, sprzyja adaptacyjności i elastyczności, co czyni tę metodologię cennym narzędziem w projektach o dynamicznych wymaganiach.

Dodatkowo, TDD opiera się na kluczowych zasadach, takich jak F.I.R.S.T., które pomagają utrzymać wysoką jakość kodu: testy powinny być szybkie (Fast), niezależne (Independent), powtarzalne (Repeatable), jednoznaczne (Self-validating) i szczegółowe (Timely). Stosowanie tych zasad pozwala na łatwiejsze zarządzanie procesem testowania, zapewniając lepszą jakość oprogramowania i minimalizując ryzyko wprowadzenia błędów w późniejszych fazach cyklu życia projektu.

Ważnym elementem TDD jest również wzorzec Arrange-Act-Assert (AAA), który stanowi uporządkowaną strukturę dla pisania testów. Rozbicie testu na trzy sekcje – "Arrange", czyli przygotowanie środowiska testowego; "Act", czyli wykonanie operacji na systemie pod testem; oraz "Assert", czyli weryfikacja wyników – zapewnia przejrzystość i spójność testów, co z kolei ułatwia ich utrzymanie i rozbudowę. Przyjęcie tego wzorca w organizacji testów wpływa na ich czytelność i zmniejsza koszty związane z utrzymaniem testów w długoterminowym projekcie.

TDD, w połączeniu z odpowiednimi wzorcami testowania, takimi jak AAA, stanowi fundament nie tylko dla tworzenia wysokiej jakości oprogramowania, ale także dla rozwoju kultury ciągłej poprawy wśród zespołów programistycznych. Każda iteracja cyklu testów poprawia jakość kodu, co pozwala na szybsze reagowanie na zmieniające się wymagania i gwarantuje większą stabilność końcowego produktu.

Przy wdrażaniu TDD w organizacji warto również pamiętać o kilku kluczowych aspektach: po pierwsze, należy zadbać o odpowiednią edukację zespołu programistycznego, ponieważ samo zrozumienie teorii TDD nie wystarczy – wymaga to praktycznego zastosowania w codziennej pracy. Po drugie, ważne jest, by zespół programistów był gotowy do pracy w sposób iteracyjny, co oznacza, że projektowanie i rozwój funkcji odbywa się stopniowo, z każdym cyklem testów poprawiającym jakość kodu. Trzecią istotną kwestią jest zapewnienie odpowiednich narzędzi wspierających TDD, takich jak odpowiednie frameworki testowe, narzędzia do integracji ciągłej i systemy do zarządzania wersjami kodu, które umożliwiają sprawne i szybkie wdrażanie kolejnych iteracji cyklu TDD.

Jak efektywnie korzystać z narzędzi debugowania w Visual Studio

Debugowanie to jeden z kluczowych procesów, który decyduje o jakości oprogramowania i efektywności pracy programisty. Prawidłowe zrozumienie, jak działa aplikacja oraz precyzyjne określenie błędów, to podstawowe umiejętności, które każdy programista musi opanować. Aby skutecznie przeprowadzać debugowanie, konieczne jest zrozumienie zarówno ogólnych zasad tego procesu, jak i możliwości oferowanych przez narzędzia, takie jak Visual Studio. Debugger w Visual Studio to potężne narzędzie, które umożliwia łatwe analizowanie i diagnozowanie problemów w kodzie.

Pierwszym krokiem w debugowaniu jest określenie, w jaki sposób kod działa w rzeczywistości. Najlepszym sposobem na znalezienie przyczyny błędu jest reprodukcja problemu. Często to właśnie odtworzenie błędu pozwala na zrozumienie, co dokładnie nie działa. Jeśli jednak nie uda się tego zrobić, warto sprawdzić środowisko, w którym wystąpił błąd, przeanalizować komunikaty o błędach, a także ocenić stan systemu w momencie, gdy problem wystąpił. Często błędy powtarzają się w określonych warunkach, a zrozumienie tego może pomóc w szybszym znalezieniu rozwiązania.

Debugowanie staje się o wiele łatwiejsze, gdy korzystamy z odpowiednich narzędzi. W nowoczesnych środowiskach programistycznych, takich jak Visual Studio, mamy dostęp do zaawansowanych funkcji debuggowania. Dzięki nim możemy dokładnie śledzić, jak nasz kod się wykonuje, i w prosty sposób diagnozować błędy.

Jednym z najważniejszych kroków w debugowaniu jest ustawienie punktu przerwania. Punkt przerwania to miejsce w kodzie, w którym program zatrzymuje się, umożliwiając nam dokładne zbadanie stanu aplikacji w tym momencie. W Visual Studio punkt przerwania ustawia się, klikając na lewą stronę numeru linii w pliku źródłowym. Po ustawieniu punktu przerwania, należy uruchomić debugowanie, aby zobaczyć, co dzieje się z aplikacją. Podczas sesji debugowania program zatrzymuje się na ustawionych punktach przerwania, a my możemy analizować jego stan i krok po kroku przechodzić przez kod.

Aby poruszać się po kodzie podczas debugowania, Visual Studio oferuje trzy podstawowe opcje:

  • Step Into (F11) – Używając tej opcji, możemy "wejść" do kodu metody lub funkcji, która jest wywoływana w bieżącej linii. Jeżeli w danej funkcji znajdują się inne wywołania, przejdziemy do najgłębszego poziomu wywołania.

  • Step Over (F10) – Opcja ta pozwala na wykonanie bieżącej linii kodu, a następnie zatrzymanie się na kolejnej linii w tej samej metodzie. Jeżeli w kodzie znajduje się wywołanie funkcji, ta funkcja zostanie wykonana bez wejścia do niej.

  • Step Out (Shift + F11) – Używając tej opcji, wychodzimy z bieżącej funkcji, a program wykonuje resztę kodu tej funkcji, zatrzymując się dopiero po jej zakończeniu.

Oprócz tych podstawowych opcji, Visual Studio 2022 oferuje również zaawansowane funkcje nawigacji, które mogą znacznie ułatwić debugowanie.

Run To Cursor (Ctrl + F10) to jedna z takich funkcji, pozwalająca na szybkie przejście do określonego miejsca w kodzie i wykonanie go aż do tej linii. Funkcja ta jest niezwykle przydatna, kiedy chcemy przeskoczyć do konkretnych fragmentów kodu, ale nie chcemy zatrzymywać się na każdym punkcie przerwania. Warto pamiętać, że linia, na którą chcemy przejść, musi być częścią wykonywanego kodu, inaczej funkcja nie zadziała.

Force Run to Click to nowa funkcja dostępna w Visual Studio 2022, która pozwala na pominięcie punktów przerwania i wyjątków pierwszej szansy, co daje większą swobodę w testowaniu nowych fragmentów kodu bez zakłócania przebiegu debugowania. Użycie tej funkcji polega na najechaniu kursorem na daną linię w kodzie, przytrzymaniu klawisza Shift i wybraniu opcji "Run execution to here". Program będzie kontynuował wykonanie kodu aż do wskazanej linii, ignorując wszelkie przerwania i wyjątki, które mogłyby przerwać jego działanie.

Po przejściu przez kod, ważne jest, aby umieć zrozumieć, co dzieje się z naszą aplikacją w danym momencie. W tym celu Visual Studio oferuje kilka narzędzi, które pozwalają na analizowanie stanu aplikacji. Warto zapoznać się z funkcjami okien debugowania, które umożliwiają dokładne śledzenie wartości zmiennych i obiektów.

  • Okno Autos pokazuje zmienne i wyrażenia, które są automatycznie oceniane przez debugger. Umożliwia to łatwe monitorowanie najistotniejszych zmiennych w bieżącym kontekście wykonania kodu.

  • Okno Locals wyświetla wszystkie zmienne lokalne w bieżącym zakresie. Może to być przydatne, gdy chcemy dokładnie sprawdzić stan wszystkich zmiennych w danym momencie.

  • Okno Watch pozwala na ręczne dodanie zmiennych lub wyrażeń, które chcemy monitorować podczas debugowania. Dzięki tej funkcji możemy śledzić zmiany wartości zmiennych w czasie, co jest niezwykle pomocne przy diagnozowaniu błędów.

  • Okno Call Stack to jedno z najważniejszych narzędzi debugujących, które pozwala zobaczyć, jakie metody lub funkcje zostały wywołane przed osiągnięciem bieżącego punktu wykonania kodu. Umożliwia to pełniejsze zrozumienie przepływu wykonania w aplikacji.

Każda z tych funkcji wprowadza nowy poziom precyzji w procesie debugowania, pozwalając programistom na szybkie zrozumienie, co dzieje się w aplikacji i gdzie może występować problem.

Efektywne korzystanie z narzędzi debugowania pozwala nie tylko na szybsze znajdowanie błędów, ale także na lepsze zrozumienie kodu i jego działania. To z kolei przekłada się na wyższą jakość oprogramowania i zwiększoną produktywność programisty.