Making sure data is valid and business rules are kept

fitness
workout
gym
sports
personal trainer
venture capital
startup

Our Fitradar back-end solution is created based on Clean Architecture as described in this article and explained in this conference talk. One part of the back-end solution is incoming request validation, and in order to implement it as a part of the MediatR pipeline we are using FluentValidation library that replaces built-in ASP.NET Core validation system. At the beginning of the project it seemed that all we have to do is just to create a custom validator derived from AbstractValidator and perform the validation of an Application Model in a single class. And that is how we started to implement the validation. And since the library has quite enhanced capabilities that allow implementing complex validation rules for a while we didn’t notice any problems. Until the moment when we realized that not all validation rules are simple incoming Data Model validation. Some of the rules expressed our business logic rules and restrictions. And so we started to think about splitting the rules across the layers and following are multi step validation solution we came up with:

  • Application level validation. At this level incoming JSON data model fields validation is performed. The field types are validated automatically by ASP.NET core built-in Model binding but the other validation rules are executed by FluentValidation including:
    • required field validation
    • text field length validation
    • numeric field range validation
  • Domain level validation. At the domain level we apply Domain Driven Design approach and therefore instead of FluentValidation we decided to use Specification pattern. We liked the idea that we can move the validation logic outside the Domain Entity to the separate Validator. By doing that we were able to bind validation logic to incoming commands instead of Domain Entity. For example we have an entity SportEvent and several commands that call methods inside that entity like Update Sport Event and Cancel Sport Event. Now because the different commands have different business requirements for the same Entity property it would be hard to implement them with FluentValidation. For example property BookedSeats in case of Update Sport Event command should be 0, but in case of Cancel Sport Event command it is allowed that someone has already booked a particular Sport Event. And bellow is how the Cancel Sport Event validator looks like:
public sealed class EventCancellationValidator : EntityValidatorBase
{
    public EventCancellationValidator()
    {
        AddValidation("CancellationTimeValidation",            
                new ValidationRule<SportEventInstance>(
                new Specification<SportEventInstance>(sportEvent =>
                    sportEvent.StartTime > DateTime.UtcNow),
                ValidationErrorCodes.CANCELLATION_TOO_LATE, "It is not possible to cancel the 
        Sport Event after it has started", "SportEventStartTime"));
    }
}
  • Database level validation. For accessing database we are using Entity Framework Core and to make sure the database models are in tune with database constraints we are using built in property attributes and classes that implement IEntityTypeConfiguration interface that allows to define database constraints like Primary Key, Foreign Key and Unique Key.

P.S. Please follow our Facebook page for more!

SwiftUI Tricks: Part 1

Photo by Clint Patterson on Unsplash

This is the first of mini articles in a series of SwiftUI tips and tricks.

One of the common tasks in mane applications is to determine screen width and layout items accordingly. FitRadar is not an exception. Many UI elements should be adjusted to screen size. There are two problems, tho: “screen” and “width”.

Screen

Most often developer’s think of a “view on screen” when saying “screen”. Physical screen size is equal to view controller size and vice versa. Yet we know that today (as per middle of 2021) we have iPad which allow run two apps side by side, or even one app in two “panels”. Know knows what else Apple introduce in future. We expect our fitness app to run on all possible devices: phones, tablets, watches, etc. So, we can’t rely on physical screen.

Width

Since there is no yet (as per middle of 2021) devices with changing screen, most often developers think of a width of screen as a constant value. However, changing screen zoom (General -> Display & Brightness ->Display Zoom) actually change it. The other and most common scenario: rotation.

So, knowing these two problems we cannot rely anymore on something simple as

UIScreen.main.bounds.size.width

GeometryReader

GeometryReader is second most advised way to get current view geometry. It does it best, but practise show that item places inside it acts differently on iOS 13 and iOS 14. And we actually want to avoid place our UI elements inside it.

For the trick we use PreferenceKey. Just add following code somewhere in project

struct SizePreferenceKey: PreferenceKey {   typealias Value = CGSize   static var defaultValue: Value = .zero   static func reduce(value: inout Value, nextValue: () -> Value) {    value = nextValue()   }}

Next, define some variable to keep current screen width

@State private var screenWidth: CGFloat = 0

Place geometry reader somewhere on the view which size you need to track. But other UI elements can now be placed outside GeometryReader

VStack {    GeometryReader { proxy in        Spacer()         .preference(key: SizePreferenceKey.self, value: proxy.size)    }    .frame(height: 1)    .onPreferenceChange(SizePreferenceKey.self) { preferences in        self.screenWidth = preferences.width    }    Rectangle()        .fill(Color.red)        .frame(width: screenWidth / 2, height: screenWidth / 3)}

This solution works equally on iOS 13 and 14. Enjoy!

P.S. Please visit our website: https://www.fitradar.me/ and join the mailing list! Fitness is closer than you think.

P.S.S. Text by https://dmi3j.medium.com/

Performance or Readability

sports
venture capital
startup

In our Fitradar backend solution we are heavily using a database in order to implement the necessary use cases. Almost every call to our backend API includes calls to the database. In order to make it easier to work with database from C# code we are using Entity Framework Core. The library allows us quickly and easy save C# objects in database and fetch persisted C# objects from the database. In many use cases the EF Core is used just for these basic operations – saving and fetching but the business logic is isolated in other classes. Nevertheless for some use cases we discovered that it is more straightforward to execute the business logic directly in the database in the form of stored procedures or user functions. And in this article I wanted to share some of the experience we had while were working on complex database operations and the solution we arrived at.

One of the main reasons why we started to consider moving some parts from the C# code to the database was the user experience. We noticed that some operations on the mobile application are taking considerable amounts of time and might degrade overall user experience and we started to look how to improve the performance of those slow operations. Some of the reasons we discovered that were causing the long response time were multiple calls to the database and unoptimized database operations. Striving for the clean code in our backend solution we tried to avoid stored procedures, user functions and triggers. Introducing SQL code that can’t be mapped to the C# code within a single use case would mean introducing another codebase. So far EF core allowed us to abstract from SQL code and we very happy to have all the logic in C# code. Besides one more language and codebase there were following issues that were holding us back from using SQL directly:

  • Adding SQL code in DbContext in the form of strings would take away the Intellisense for SQL and that would make us deal not only with logic errors but with syntactic errors as well in the runtime.
  • Refactoring with Visual Studio built-in tools would become more complex
  • In case we needed to debug our method that uses stored procedure or fires SQL trigger we would have to debug C# and SQL code separately
  • Working with two codebases readability of single use case is degrading – in order to understand the full logic we have to switch between C# and SQL
  • There are different logging systems for ASP.NET Core and SQL and therefore it is harder to keep unified log format.
  • More complex deploy process

But at the same time for complex persistence and database query operations we would have:

  • Significant gain in performance
  • Terse code, since SQL is specifically designed to work with relational databases and many operations can be expressed in much shorter code compared with C# and LINQ without losing the readability.

The main question we had to answer in order to understand whether we need to move some of the logic to stored procedures, triggers and user functions was: “Is the gain in performance worth it?” For some use cases we could see the improvements even with the test data and for the other use cases we predicted that changes we are planning to introduce will start to impact the performance once certain amount of data will be stored in a database. And so we decided to move some of our logic from C# to SQL code, but before that we really wanted to mitigate some of the above-mentioned problems we discovered during analysis. And to do that we decided to create separate SQL Server Database Project instead of keeping the SQL code in EF Core DbContext class and by doing that we solved the problem with structuring the code, Intellisense and SQL code maintenance.

P.S. Visit our website: https://www.fitradar.me/ and join the waiting list. We launch very soon!

Testing all links in the chain

Our Fitradar solution is using various third party services, and therefore the Integration tests in our solution became a very important part next to the Unit tests. In our backend application we are trying to follow the ideal Test Pyramid

Ideal Test Pyramid

but for some Use cases it makes more sense to run all the involved services rather than replace them with Mock objects, mostly because there is no complex logic involved in particular Use Case; it is rather straightforward without conditionals and loops. And on the other hand the Integration Tests give us more assurance that the Use Case is robust and works as expected. And so for some Use Cases we started to prefer Integration tests instead of Unit tests and our test pyramid became a little bit distorted. The following parts in our back end application are tested by Integration Tests:

  • ASP.NET Core Model Binding. Once we discovered that produced JSON data for some C# objects is not exactly as we expected, and that some incoming JSON is not parsed as we expected we started to test and verify that incoming and outcoming data are transformed as we are expecting
  • ASP.NET Core and third party libraries configurations defined in Startup file. The configurations can be tested only at runtime and therefore to test these configurations we have to run the test web server and make some requests against the server. Some of the configurations we are testing are following:
    • Dependency injection
    • AddMediatR and FluentValidation configuration
    • ASP.NET Core Authentication and Authorization integration with  Firebase Authentication
  • Entity Framework produced SQL code. Especially for complex queries. And Entity Framework save and update logic for complex types where at runtime some nested objects might have different EntityState than parent object. And any complex logic interacting with Entity Framework
  • Integration with Azure Services like Service Bus and Azure Web Functions
  • Integration with Stripe

The crucial factor that made our team write more Integration Tests is the new ASP.NET Core test web host and test server client. It allowed us to quickly setup the test server with our back-end application and run the requests against our API. By using the test host we were able to test most of the configurations in the Setup file. It was harder to test our back-end parts that were part of the Azure Functions, but after some error and trial we were able to create a test web host for the Azure functions as well and issue the calls that triggered the Functions. And here is how we test the sport event cancellation Use Case that is triggered by message from Service Bus queue:

        [Fact]
        public async Task TestUnpaidEventCancelled()
        {
            var resolver = new RandomNameResolver();

            IHost host = new HostBuilder()
                .ConfigureWebJobs()
                .ConfigureDefaultTestHost<CancelSportEventFunction>(webJobsBuilder => {
                    webJobsBuilder.AddServiceBus();
                })
                .ConfigureServices(services => {
                    services.AddSingleton<INameResolver>(resolver);
                })
                .Build();

            using (host)
            {
                //Arrange
                await host.StartAsync();
                _testFixture.SeedSportEvent();
                await _testFixture.BookSportEventInstance();
                _testFixture.AddCommentToSportEventInstance();

                //Act
                await _testFixture.SendMessageAsync("CanceledEvents",
                    _testFixture.CanceledSportEventInstance.Id.ToString());
                await _testFixture.WaitUntilSportEventInstanceIsCancelled();

                //Assert
                //_output.WriteLine($"Found {parsedOrders.Count} invoices.");
                var calendarEvents = _testFixture.GetCalendarEvents();
                Assert.Empty(calendarEvents);
                var order = _testFixture.GetCancelledSportEventOrder();
                Assert.NotNull(order);
                var msg = _testFixture.GetVisitorsInboxMessage();
                Assert.NotNull(msg);
                Assert.Equal(MessageSource.CANCEL_EVENT, msg.Source);
                var statistics = _testFixture.GetVisitorsInboxStatistics();
                Assert.NotNull(statistics);
                Assert.Equal(1, statistics.NumberOfCancelMessages);
            }
        }

P.S. Visit our website: https://www.fitradar.me/ and join the waiting list. We launch very soon!

SwiftUI and UIKit interoperability

Many iOS developers started to insert SwiftUI views into existing production projects. UIHostingController makes it really easy to integrate. Yet sometimes you need it vice versa: insert a UIKit view into SwiftUI view. In FitRadar we provide calendar view to show not only your trainings, but also display other events from calendars on device. Trainers will find it easy to plan, avoid overlapping or help customers not to book training when there is important meeting planned.

Photo by Waldemar Brandt on Unsplash

This time we use power of UIViewRepresentable. In this example FSCalendar view (written in Objective-C) needs to be inserted in SwiftUI view, linked with MVC view model. Official documentation is quite laconic about it’s usage. I assume there are many ways how to embedded view behind UIViewRepresentable structure. Some advice to use Coordinator. I don’t see big value in it for our case, since I want make this view reusable and make view model be responsible for calendar view data representation.

Let’s create the “view wrapper” for calendar

import SwiftUI
import FSCalendarstruct CalendarView: UIViewRepresentable {
var calendar: FSCalendar
@Binding var isCalendarExpanded: Bool func makeUIView(context: Context) -> FSCalendar {
calendar
} func updateUIView(_ uiView: FSCalendar, context: Context) {
let scope: FSCalendarScope = isCalendarExpanded ? .month : .week
uiView.setScope(scope, animated: false)
}
}

Normally, you would want to create FSCalendar inside makeUIView(context:) but we want keep reference to it, so we create it outside and pass as reference on creation. Another option we pass via binding is calendar mode which is either month view or week view.

After this we may insert in SwiftUI as easy as

CalendarView(calendar: viewModel.calendar,
isCalendarExpanded: $viewModel.isCalendarExpanded)
.frame(maxWidth: .infinity)
.frame(height: viewModel.calendarHeight)

To support this configuration we need a view model

class HomeViewModel: NSObject, ObservableObject {
@Published var calendar = FSCalendar()
@Published var isCalendarExpanded: Bool = true
@Published var calendarHeight: CGFloat = 300.0 override init() {
super.init() calendar.delegate = self
calendar.dataSource = self
calendar.scope = isCalendarExpanded ? .month : .week
calendar.firstWeekday = 2
}
}

That’s it. Please refer to the source code for full example.

References

https://developer.apple.com/documentation/swiftui/uiviewrepresentable

https://github.com/dmi3j/calendar-demo

Txt: https://dmi3j.medium.com/

P.S. Visit our website: https://www.fitradar.me/ and join the mailing list. We are in beta stage already!

Map in iOS app

Navigation is a crucial part of many mobile applications today. We might not even realise that behind something simple as finding car for rent, food delivery or Pokemon hunting there are some big tech: GPS (satellites in the Space!!!), Google/Apple/Microsoft maps services and, of course, intelligent mobile device with plenty of microcircuit. In FitRadar we use maps services to help trainers set training location by selecting some infrastructure object (gym, stadium, public location) or set some point in unnamed location by the river or lake for many open area activities like yoga, cycling or as simple as walking.

There are simple and clear requirements for map services:

  • present map to set a point for location
  • clustering (show single point on map with number of events instead of plenty points)
  • address search

Personally I try to utilise native platform solution (when it exists) for any problem. Obviously, I started with MapKit. But there is no way to ignore Maps SDK for iOS from Google. Or even check Bing from Microsoft. Integration process for all of them is relatively simple. Some require developer account and developer key creation. But let’s compare how they work.

Map and pin

All three candidates can do simple map presenting and selection random pin with coordinates pretty well. Also displaying simple map vs satellite is very good in all SDKs. Google maps can use

Clustering

Clustering for MapKit is something they support almost out of the box. For Google Map there is custom plugin. Which seems to be supported for a very long time. I wasn’t able to find any Bing map. (Please, share a link in comments if I’m wrong.)

Address search

Google Maps SDK is and absolute winner in this category. For some reason only Google pays attention not only to world wide known places like London or New York, but it also knows something like tiny beach, on border of Riga, Latvia.

Of course, it’s not something you may advertise on WWDC, but local citizen will appreciate when volleyball trainer organise next meeting at “Salaspils pludmale” app will know exactly where it is.

Bonus

Another “+” for Google Map iOS SDK is ability to use app custom colors to match app desing. This design is a JSON file which can be edited manually (or at online editor) and shipped with app bundle.

Again, I wasn’t able to find similar functionality for Apple or Microsoft maps, but, please, feel free to add in comments if they exist.

Conclusion

So, for today, obvious choice is a Google Maps SDK for iOS. I hope some day Apple bring it attention to MapKit and make it useful for all customer around the world, including some tiny country like Latvia.

Except where otherwise noted, this work is in the public domain.

P.S. Visit our website: https://www.fitradar.me/ and join the mailing list. Our app is coming soon.

P.S.S. Text by Dmitrijs Beloborodovs

Our journey towards serverless

Recently we were working on a ticket booking and booking cancelation feature in our Fitradar solution. In our solution the booking process consists of two steps: the place reservation in a sport event and payment. And in case the user for some reason didn’t make a payment the system should execute one more step – cancel the reservation. The process becomes non trivial when each step is done in separate environments – the reservation is done on the back-end, but the payment is done on the client’s device. The most challenging part was to figure out how to cancel the reservation in cases when payment was not made or failed.

So we started to look for possible solutions. Initially we were considering Background tasks with hosted services but we didn’t like the fact that the background task will be in the same process as our main back-end service and we have to make sure the process doesn’t shut down after the request is handled. And since we were using the Azure Cloud for hosting our beck-end services the next thing we started to look at was the WebJob which seemed a very good solution for our use case until we introduced ourselves to the Azure Functions. After some investigation we came to conclusion that Azure Service Bus with message deferral and Azure Functions would be perfect solution. The idea was to send a message to the Service Bus after the user has made a reservation. The Service Bus would deliver the message to our Subscription with 15 minutes delay and our Azure Function would cancel the unpaid booking. In order to receive the scheduled Service Bus message we needed to use Azure Function with Service Bus trigger.

Once we learned more about Azure Functions we decided to use them for other tasks as well that should be done outside the usual request – response pattern. One of such tasks in our solution was User Rating calculation. The task should run on a regular basis every Sunday night. This requirement was perfect job for timer triggered Azure Function.

We started to work on our serverless functions. After the function was scaffolded we started to add our business logic. And since we already had a solid CQRS architecture in place for the main back-end service and for each use case we were creating a separate Command that was using the rest of our infrastructure we wanted to add another Command for reservation cancelation use case, but we faced some .NET Core compatibility issues. Our backend runtime was targeting .NET Core 2.2 version, but our Azure Functions runtime was targeting .NET Core 3.1. Although we could just downgrade our Functions app runtime but the documentation strongly encouraged to use version 3.1, because Function apps that target ~2.0 no longer receives security and other maintenance updates. And so we started to migrate our back-end app to the .NET Core 3.1.

We followed official documentation but still struggled to make our third party libraries work again. The biggest challenge was to find a way how to make to work FluentValidation, MediatR and Swagger together. Once we updated the FluentValidation registration in the Startup file according to the provided documentation it switched off the MediatR Pipeline Behaviors. And once we found a way how to make Pipeline Behaviors work it switched off FluentValidation rules on the Swagger UI page. The Stackoverflow and Google couldn’t help us and we started to experiment with the available settings for FluentValidation and MediatR registration. After several hours of error and trial  we found one setting that made all three libraries work together nice and smooth. Here is the peace of code that made our day:

services.AddMvcCore().AddFluentValidation(fv =>
                {
                    fv.RegisterValidatorsFromAssemblyContaining<PlaceValidator>();
                    fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
                    fv.AutomaticValidationEnabled = false;
                });

Now our Fitradar back-end can really benefit from all ASP.NET Core and Azure Functions provided functionality.

P.S. Visit our website: https://www.fitradar.me/ and join the mailing list. Our app is coming soon.

Fitness and mobile app

Hi ! My name is Dmitrijs Beloborodovs

Fitness become one of the buzzwords along with bitcoin or соvid. The first should eventually stop jumping up and down, the second should go away, yet fitness must stay forever. It is crucial to find a good personal trainer to have a smooth start and keep going for a long time. There is something that might help you with that.

Recently I joined a FitRadar team to help with mobile app development. What is a FitRadar (https://fitradar.me) in a nutshell? Briefly: we bring trainers and audience together. Today, your service must be available via different channels: website, integrated in social media and of course, has its own mobile app. A mobile device knows quite much information about you and your habits: your location, language preferences, your schedule and sometimes even specific health metrics (HealthKit is a good example). In other words, it knows enough to propose you a best fitness trainer or sport community in your area, with respect to your timetable, interest or by your friends recommendation. When you start building something great like this, you want to be sure are are building on solid foundation. Here is the first question you might want to evaluate:

Should I go cross platform or native?

Crossplatform solutions (i.e. Flutter, React Native) might look attractive initially, yet brings problems later: super long polishing to achieve smooth and nice UI/UX to mimic platform (all those bounces and responsiveness, etc) and hard path of integration with platform native hardware (location, calendar, etc). So, for us, answer is go 100% native. Stay tuned to know how well we managed to achieve a primary goal of our mobile app — bring nice experience of finding a sport fo your dreams.

Visit our website: https://www.fitradar.me/ and join the mailing list. Our app is coming soon!

P.S. Source: https://medium.com/@dmi3j/fitness-and-mobile-app-3dca370d8e10

Being unique is not always a good thing

The other day I was reviewing my colleagues’ code. It was back-end code written in C#. I noticed that he introduced a class that is very similar to the structure I was quite sure existing in the .NET base library. I found that structure in Microsoft documentation and we agreed that it is better to use .NET type instead of introducing the same type with a different name. After that occasion, I recalled several other cases when I saw the unique solutions for the problems that could have been solved by well-known pattern or practice. My gut feeling was telling me then that it is not a good idea to introduce your own solution for a problem that is already solved by someone else, but I have never really thought what problems such decision can introduce in the project. And so in this article, I wanted to share some thoughts regarding the widely accepted and unique solutions in software development.

First let’s make it clear that any best practice, framework, algorithm or technology was a unique solution in their time. Then when exactly one or another solution became widely accepted?

  • There are solutions in computer sciences that can be measured, like algorithms. In order to estimate the cost of algorithm calculation Big O notation was introduced. When someone comes up with a new algorithm for common problem, for example sorting, we can simply compare how fast each algorithm solves the problem using big O, and choose the one that meets our criteria. And if the new algorithm beats the old one in performance working on the same data, then it becomes the new standard.
  • But most of the technologies, frameworks, patterns and best practices can not be compared by introducing measurable parameters. Think about programming languages or frameworks. There is noway you can make an unambiguous claim which language or framework is better. Then how to find out what is the best language or framework for the given problem. Let me share a story from my youth that might give some insight how the new solution become widely accepted. I remember the story that was shared by my Assembler class professor at University. He started his computer scientists career when software was written in punch cards and he became very good at writing machine code and later at Assembler. And when the first compilers emerged such as FORTRAN and ALGOL he was very skeptical regarding these new languages and the compiling technology in general, because he didn’t believe that the compilers algorithm is able to produce the same quality machine code as a skilled Assembler developer. And in the fifties and sixties well written assembly code really metered, because every byte was counted and his reasoning at that time was valid. But time passed by the hardware and compilers improved and we see that most of the code even in embedded systems now days is written in high level programming languages. The same story goes for programming paradigms – the business application world started with procedural programming and today it ended with Object oriented programming. In Windows and Mobile apps we started with Forms and Activities and today ended with MVVM. So it looks like for such things as programming languages and frameworks more or less useful criteria that we can use is
    • the amount of time the technology is used,
    • amount of software written using the the particular technology
    • number of developers actively using the particular technology

And still all these criteria are not so reliable as big O for algorithms.

In case of algorithm I think it is quite clear that if there is already an algorithm that solves the problem it is pointless to write your own, unless you can produce better one. In case of frameworks I would follow the same logic – if there is an well known framework that can solve the problem it is much safer to relay on the majorities opinion (although the majority can be wrong) rather than on your own single point of view. Even if the framework or pattern will be rejected in the near future at this moment:

  • it is much more tested than your own solution, and therefore there are much more chances to have a flaw or even bug in your solution than in the widely accepted solution
  • it will be much easier for other developers to work with widely accepted solution than yours, because there is much more documentation and all kind of sorts information about the widely accepted solution than you can ever produce. And this will become crucial when your solution will start to live it’s own live

Visit our website: https://www.fitradar.me/ and join the mailing list. Our app is coming soon.

P.S. We are hiring: http://blog.fitradar.me/we-are-hiring/