Table of Contents
Z pamiętnika SaaSa jest to cykl artykułów, w których opisuję moje doświadczenia zdobyte przez ostatnie 10 lat pracy nad komercyjnymi aplikacjami SaaS, ze szczególnym uwzględnieniem easyRenti. Opisuję decyzje, które podjąłem, jak i konkretne rozwiązania zastosowane w programie.
Wstęp
Mój najnowszy projekt, aplikacja do zarządzania najmem mieszkań easyRenti, jest dobrym przykładem tego jak SoloProgramista podchodzi do tworzenia programu w modelu SaaS. W związku z tym, iż easyRenti jest dość rozbudowany, jego wartość edukacyjna nie jest najlepsza. Zrozumienie, w jaki sposób różne moduły działają, byłoby trudne. Dlatego zdecydowałem się na potrzeby bloga i cyklu Z pamiętnika SaaSa, stworzyć nowy projekt, oparty o rozwiązania, które z powodzeniem działają w easyRenti.
Jeśli interesują Cię inne moje projekty, możesz poczytać o tym tutaj.
W przeciągu najbliższych tygodni, będę publikował nowe artykuły, w których dodam coś nowego do projektu. Każdy post będzie kontynuacją cyklu Z pamiętnika SaaSa, jednak będzie też zamkniętą całością. Oznacza to, że nawet jeśli nie interesuje Cię process budowania aplikacji, a jedynie sposób, w jaki zaimplementowałem konkretne rozwiązania, to przeczytawszy konkretny artykuł, powinieneś zdobyć interesujące Cię informacje.
Przed rozpoczęciem, małe wyjaśnienie. Cykl Z pamiętnika SaaSa skupia się na technicznych aspektach tworzenia programu. Nie będę zajmował się sprawami w stylu:
- Skąd wziąć pomysł
- Walidacja pomysłu
- Szukanie klientów
W Internecie jest wiele miejsc, gdzie znajdziesz porady w tych kwestiach. Tutaj zakładam, że masz pomysł na program, jesteś zdecydowany go stworzyć, klienci już czekają (lub wiesz jak ich pozyskać) i trzeba jak najszybciej i najmniejszym kosztem go stworzyć.
Założenia
Nasza przykładowa aplikacja będzie bardzo oryginalna. A mianowicie będzie umożliwiała tworzenie notatek 🙂 No dobra. Z tą oryginalnością trochę przesadziłem. Ale sama funkcjonalność tutaj nie ma znaczenia. Tworząc aplikację SaaS (dowolną) trzeba zaimplementować wiele mechanizmów, które są w większości tego typu programów, tj:
- Zaprojektowanie architektury
- Wybranie stacku technologicznego
- Tworzenie konta i logowanie
- Obsługa wielu użytkowników
- Testy automatyczne
- Płatności
- Tryb demo
- Przechowywanie plików w chmurze
- Konto free/premium
W cyklu Z pamiętnika SaaSa skupimy się właśnie na tych dodatkowych elementach. Pokaże Ci, w jaki sposób zaimplementowałem powyższe rzeczy w easyRenti oraz wyjaśnię, dlaczego zrobiłem to w taki, a nie inny sposób. Pamiętaj, iż decyzje, które podjąłem, były kreowane przez poniższe założenia:
- Jestem sam, więc wszystko jest na mojej głowie. Rozwiązanie musi być skuteczne (powinno rozwiązywać problem), ale też proste. Nie chcę poświęcić na jakiś element miesiąca, jak mogę zrobić coś podobnego w tydzień.
- Efektywne wykorzystanie dostępnych zasobów. Jeśli mogę skorzystać z gotowego rozwiązania/komponentu, to to robię. Implementuję własnoręcznie tylko to co muszę.
- Minimalizacja kosztów. Samo stworzenie aplikacji nie powinno się wiązać z żadnymi kosztami (albo z bardzo małymi). Częściowo ten punkt stoi w sprzeczności z powyższymi. Jeśli chciałbym zaoszczędzić czas to mogę kupić gotowe rozwiązanie. Jednak w przypadku SoloProgramisty, który rozpoczyna swój projekt, zakładam, że minimalizacja kosztów ma większe znaczenie.
Projekt
Wspominałem już, że testowy program będzie służył do tworzenia notatek. Oto cała funkcjonalność:
- Tworzenie notatek
- Edycja notatki
- Usuwanie notatki
- Wyświetlanie listy notatek
- Wysyłanie przypomnień
Docelowo chciałbym, aby aplikacja była hostowana w jednej z publicznych chmur (Azure, AWS, Google Cloud). Założenie jest takie, że utworzenie konta jest bezpłatne. Funkcjonalność darmowej części będzie ograniczona. W tym momencie jeszcze nie znam konkretnych różnic, jednak na tym etapie nie mają większego znaczenia. Często warto przez pierwszy okres istnienia aplikacji na rynku, dać pełną funkcjonaność za darmo pierwszym użytkownikom – dzięki temu zdobyty feedback pomoże udoskonalić program.
W easyRenti (a także w naszej testowej aplikacji) pominąłem rozróżnianie kont Premium i Free. Na to przyjdzie pora, gdy aplikacja zdobędzie większą liczbę użytkowników. Obecnie szkoda na to czasu.
Architektura i technologie
Wiedząc jakie są wymagania funkcjonalne projektu, możemy przejść do zaprojektowania właściwej architektury. W większych projektach zwykle bierzemy pod uwagę następujące czynniki:
- Przewidywane obciążenie aplikacji
- Ilość danych
- Wydajność systemu
- Koszta
- Możliwości zespołu
Mając wybraną architekturę systemu, czas zdecydować się jakich technologii użyć, aby jak najlepiej spełnić wymagania.
W przypadku SoloProgramisty, podejdziemy do sprawy z innej perspektywy. Najważniejszymi czynnikami jest możliwość zespołu i koszta. Zespół jest jednoosobowy, więc jego możliwości są mocno ograniczone, tak jak budżet, który chcemy przeznaczyć. W związku z tym architektura musi:
- Być jak najprostsza – ale spełniająca wszystkie nasze wymagania. To że chcemy skrócić czas wytworzenia oprogramowania do minimum, to nie znaczy, że odwalamy fuszerkę. Ma być dobrze, ale prosto. Zakładam, że tworząc swój nowy produkt, nie masz miliona użytkowników, którzy tylko czekają na Twoją apkę. Jeśli, jednak spodziewasz się takiego obciążenia od początku, to oczywiście architektura musi to uwzględnić.
- Minimalizująca koszta – np. hostingu
- Wykorzystywać znane technologie – opieram się w większości na językach, frameworkach i wzorcach projektowych, które znam. Dzięki temu jestem w stanie stworzyć program w miarę szybko i dobrze.
Czytając ostatni punkt, możesz zadać pytanie, czy w takim razie tworząc projekt powinieneś wybrać technologię Legacy, w której programujesz już od 15 lat, więc znasz ją najlepiej. Moim zdaniem, zdecydowanie nie. Pakowanie się na początku projektu, w coś co w danym czasie jest przestarzałe przyniesie więcej problemów niż to warte. Często słyszę argument, iż pierwsza wersja będzie napisana w starej technologii, a jak program się przyjmie, to druga wersja zostanie napisana jak należy. Brzmi fajnie, ale moje doświadczenia pokazują, że druga wersja może nigdy nie powstać. I nie dlatego, że nie ma klientów więc projekt upadnie. Wręcz przeciwnie, klienci są, używają już pierwszej wersji i oczekują nowych ficzerów. Wtedy okazuje się, że nie ma czasu na przepisywanie aplikacji. W takiej sytuacji z każdym miesiącem aplikacja staje się coraz większa i tym ciężej ją przepisać.
Ale czy na pewno jest to jakiś problem? Jeśli stara technologia spełnia wymagania to chyba nie ma o czym mówić? Niestety jest.
Wady Legacy
W branży IT technologie Legacy nie mają dobrej sławy. Większość z nas chce pracować w najnowszych technologiach, o których słyszymy na konferencjach i czytamy na blogach. I choć może brzmi to dziwnie, ale między innymi to sprawia, że pakowanie się w legacy jest błędem. Nawet jeśli dla Ciebie nie jest problemem praca przy projekcie, który lata świetlności ma już za sobą, to dla innych programistów będzie to problem. Projekt zacząłeś samodzielnie, ale jeśli osiągniesz sukces, to jest duża szansa, że postanowisz zatrudnić programistów. I gdzie ich znajdziesz? Kto będzie chciał pracować w czymś co już „trąci myszką”? W dzisiejszych czasach jest niedobór na rynku pracy, firmy mają duży problem zatrudnić odpowiednią ilość ludzi do swoich projektów. Atrakcyjność technologii wykorzystywanych przez firmę, często jest jednym z czynników, dla których ktoś zmienia pracę.
Drugim problemem z legacy jest to, iż coraz mniej ludzi w tej technologii pracuje, w związku z tym jej możliwości są ograniczone. Nie powstają nowe wersje bibliotek, które implementują najnowsze rozwiązania, gdyż reszta świata już przeszła (albo przejdzie w najbliższej przyszłości) na coś nowego. A Ty będziesz mieć problem, aby dodać do swojej aplikacji np. obsługę najnowszej wersji protokołu TLS.
Skrzynka z narzędziami
Reasumując, jak rozpoczynasz nowy projekt, korzystaj z aktualnych technologii. Nie muszą to być rzeczy eksperymentalne, bo one też niosą ze sobą ryzyko. Jednak gdy piszesz aplikację desktopową w .NET, to nie zastanawiaj się czy Windows Forms, czy WPF – weź WPF. W przypadku aplikacji webowej, zapomnij o Web Forms – idz w MVC i najlepiej w .NET 6.
Jak w takim razie pogodzić używanie aktualnych technologii z faktem, że chcemy w większości korzystać z tego co znamy? Oczywiście musimy znać aktualne technolgie, pytanie tylko jak to zrobić. W tym momencie dochodzimy do kwestii rozwoju osobistego programisty. W tej pracy, nauka nowych rzeczy jest niezbędna. Jeśli chodzi o mnie to wykorzystuję tworzenie własnych projektów między innymi do tego, aby rozwinąć swoje umiejętności. Stąd 80% jest mi znana, ale 20% to nowości. Jak to wyglądało w przypadku easyRenti?
Znane:
- .NET i C#
- ASP.NET MVC
- NHibernate
- Podstawy Azura
- HTML/CSS
Nieznane:
- .NET 5 (Core)
- ASP.NET Core
- Blazor
- Azure Functions
- Azure Blob Storage
Z powyższej listy wynika, że samego dotneta znałem od wielu lat, jednak nie miałem okazji pracować z najnowszą wersją .NET Core. Podobnie jeśli chodzi o ASP.NET MVC i najnowszą wersję ASP.NET Core. Nie jest to duża niewiadoma, więc spokojnie da radę ogarnąć różnice. Nową technologią, którą chciałem się nauczyć był Blazor. Jednak zauważ, że nie wybrałem całkowicie nowego języka, frameworka itp. Tworząc aplikację w Blazorze, piszemy w C# i korzystamy z klas .NET, dzięki czemu dla programisty .NET nie jest to duży problem, aby stworzyć w tym aplikację.
Z drugiej strony korzystam z NHibernate, który jest z nami już ponad 10 lat i cały czas jest rozwijany. Nie widzę osobiście powodu, żeby zmienić tego ORM na np Entity Frameworka, w przypadku, gdy znam dobrze NHibernate. Co więcej, w mojej programistycznej „skrzynce z narzędziami”, jest on kluczowym komponentem, dzięki któremu, jako SoloProgramista, jestem w stanie tworzyć i testować aplikacje SaaS. Będzie on częstym gościem na moim blogu:)
Wracając do wyboru technologi dla easyRenti (i testowego projektu) będą to:
- .NET 5
- ASP.NET Core
- Blazor
- Bootstrap 5.1
- NHibernate
- MS Sql Server
- Azure
Dlaczego .NET 5, a nie .NET 6? Tylko dlatego, że rozpoczynając easyRenti, dopiero wchodził .NET 5, a ten cykl artykułów bazuje na doświadczeniach z prac nad tą aplikacją. Gdybym rozpoczynał nowy projekt dzisiaj, pewnie byłby to już .NET 6.
Co z architekturą?
Narazie wiemy w czym będziemy robić, ale nie wiemy jak.
Aplikacja ASP.NET Core
Głównym elementem systemu będzie aplikacja ASP.NET Core, która spełnia 3 funkcje:
- Landing Page – strona główna programu, na którą będą trafiać potencjalni użytkownicy
- Web API – zawiera całą logikę biznesową aplikacji. Dzięki wystawieniu API, w przyszłości nie będzie problemu z napisaniem programów na smartfony, czy desktop.
- Serwer autentykacji – żeby zalogować się do aplikacji, użytkownik będzie przekierowany bezpośrednio do naszej aplikacji ASP.NET Core
Aplikacja kliencka Blazor
Następnym komponentem będzie aplikacja SPA napisana w Blazor. Tutaj zdecydowałem się na podejście WebAssembly, co pozwoli w przyszłości dodać obsługę trybu Offline. Wymusza ono też wystawienie API (aplikacja kliencka nie ma dostępu do bazy danych), co jest dla mnie zaletą, gdyż jak wspomniałem wcześniej, z tego API będą korzystać inne aplikacje klienckie.
Scheduler job Azure Functions
Ostatnim elementem jest serwis do wysyłania cyklicznych powiadomień. Będzie to oddzielna aplikacja napisana z wykorzystaniem Azure Functions.
Jeśli chodzi o hosting to jak już dobrze wiesz, wybrałem chmurę Microsoftu czyli Azure. Dlaczego właśnie tą? A dlaczego nie? Dla mnie jest to naturalny wybór ze względu na wykorzystanie technologii Microsoftu do stworzenia aplikacji (.NET 5). Jest to także okazja, żeby poznać coś co jest na topie i dodanie nowego narzędzia do swojej skrzynki.
Od początku, źródła programu trzymam na Azure Devops. Dodatkowo za darmo dostajemy 1500 minut miesięcznie na CI/CD, co oczywiście wykorzystałem. O bug trackerze chyba nie muszę wspominać. Jeśli jeszcze nie korzystałeś z Azure Devops i nie masz pomysłu, gdzie wrzucić swój projekt, to polecam właśnie tę platformę.
Estymacja projektu
Zaczynając projekt easyRenti nie zakładałem żadnego deadline’u. Dodatkowo pracowałem nad nim głównie po godzinach i w weekendy. Do dnia pisania tego artykułu, zajeło mi to 740h, czyli 3 miesiące pracy po 8 godzin. W związku z tym, iż rozwijałem go po godzinach, trwało to ponad 6 miesięcy.
Jeśli masz ochote zobaczyć, ile w tym czasie udało się zrobić, to na stronie https://renti.easywsdl.com mozesz skorzystać z Live Demo i ocenić zakres projektu.
Podsumowanie
Zaczynając nowy projekt, musimy podjąć wiele decyzji, które będą miały wpływ na końcowy rezultat. Powinniśmy realnie oceniać nasze możliwości i dobierać rozwiązania, które jesteśmy w stanie zaimplementować. Adam Mickiewicz pisał:
Mierz siłę na zamiary,
Nie zamiar podług sił.
Pieśń FIlaretów
Zachęcał, aby stawiać sobie ambitne cele, a siły zawsze się znajdą. Z moich doświadczeń SoloProgramisty wynika jednak, że lepiej aby nasze zamiary były dostosowane do możliwości. Zbyt ambitnego projektu w pojedynkę nie dowieziemy do końca – prędzej się zniechęcimy.
W następnym artykule przejdziemy już do kodu. Jeśli chciałbyś dowiedzieć się czegoś konkretnego, napisz proszę w komentarzach co Cię interesuje.
Powodzenia Romek! Bardzo fajny wstęp i zarys projektu, czekam na dalsze artykuły 😉
Ciekawi mnie jak organizujesz pracę czy „motywujesz” się do rozwijania projektu. Zakładasz ileś czasu pracy dziennie, czy może starasz się każdego dnia pracy skończyć jakiś „ficzer”/kawałek logiki biznesowej?
Masz listę zadań? Jeśli tak, to gdzie ją trzymasz?
Dzięki Dawid! Z pewnością popełnię artykuł, który odpowie na Twoje pytania. Narazie moge zdradzić, iż problemu z motywacją nie mam. Pisanie programów jest tym co lubię robić. Lubię także poznawać nowe języki i techniki w programowaniu, więc po prostu łączę rozwój siebie jako programisty z pasją do programowania. Mam nadzieję, że trochę zapału przeniosę na pisanie bloga 😉
Z pamiętnika SaaSa: Zaczynamy! – SoloProgramista
Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl
[…] poprzednim artykule pokazałem, w jaki sposób zaczynam nowy projekt – czym się kieruję przy dobieraniu […]
Pomysł na pokazanie procesu tworzenia jest świetny. Życzę powodzenia.
Zastanawiam się dlaczego wybrałeś Blazora, zamiast frameworka javascriptowego?
Wpadłem na podobny pomysł i już na starcie napotkałem na różne problemy np. przetwarzanie obrazka po stronie klienta było możliwe z pomocą biblioteki js.
Dzięki. Mam nadzieję, że przydadzą Ci się treści, które znajdziesz na moim blogu.
Jeśli chodzi o Blazora to z kilku powodów:
– dla funu i nauki – od dawna C# to mój główny język, także mialem ochote zobaczyć co to jest ten Blazor, a lubię poznawać rzeczy w praktyce
– nie chciałem wchodzić w js framework z tego wzgledu, iż nie programuję w js, także wymagałoby to ode mnie sporo nauki żeby to wszystko ogarnąć (js, npm, web paki i inne cuda na kiju) – mam kumpli w pracy, którzy rzeźbią w js i nie mają lekko 😉
Jeśli zaś chodzi o wnioski odnośnie Blazora, to planuje napisać oddzielny artykuł, w którym zbiorę swoje przemyślenia. Ogólnie mogę powiedziec że sam framework dla mnie jest spoko, a rzeczy które nie można zrobić w Blazor to można wykorzystać bilbioteke js – w Blazorzre raczej łatwo używa się kodu js. także nie jest źle.
Dokładniejsze wnioski znajdziesz za jakiś czas w artykule 😉
Cześć, dzięki za dzielenie się wiedzą i przemyślenia. Aktualnie zaczynam przygodę z Saas, NHibernate i DDD. Czy polecasz jakieś źródła do nauki NHibernate
Powiem Ci, że NHibernate używam od tak wielu lat, iż nie pamiętam jak zaczynałem go poznawać. Na pewno korzystałem z oficjalnej dokumentacji, jak również Stackoverflow oczywiście w przypadku rozwiązywania konkretnych problemów. Plusem jest to, że Hibernate jest bardzo popularny w javie i wiele rozwiązań, które tam działają, można próbować użyć w NH.
Na pewno poznanie NH trochę potrwa, jednak zdecydowanie warto. Zobacz sobie mój artykuł o implementacji trybu Live Demo w aplikacji SaaS. Dzięki NH jest to bardzo proste.