When it comes to getting ready for the week, the best place to start is with your to-do list!
In my last article I mentioned that we had cases when we needed to split our back-end application across several processes and as a result we gained more flexibility when we needed to scale the application. This time I want to keep sharing some insights on why we try to keep some parts of the application loosely coupled. This time I wanted to talk about loose coupling at design time when the whole application might run in the single process. According to one of the definitions ”loosely coupled system is one in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components”. In object oriented paradigm, that we are using to create our Fitradar application, most of the code is spread among various classes and therefore the smallest component that we consider is a class. And since classes are just containers for data and functions then we usually see the loose coupling as a way how to call a function of another class with little information as possible.
The simplest way how to call a method on the other object is to create that object from a class (in Java and C# we do that by new operator) and call the needed method. But it turns out there are many cases when it is undesirable to know the class name of an object or even a specific method name during the design time and therefore there are several methods how to reduce the knowledge of a class we are going to use and a method we are going to call:
- We can replace a class with an interface or an abstract class and in such way reduce the information about the class to the subset of methods that the other classes are interested in. In Object Oriented programming this is known as Polymorphism and is one of the OOP cornerstones. It is really hard to express how important this OOP feature is. I think back in a day that feature was one of the selling points of OOP that pushed out the procedural programming. The biggest gain of using Polymorphism is a flexibility. Now we are not bound to a single code execution flow, because every function that is presented in the execution flow via interface or abstract class can be replaced with other implementation through the configuration or dynamically during a runtime. This in turn opens whole bunch of new possibilities. And the one I like the most is Unit testing. Now days it is hard to imagine how much work it would require to isolate the piece of code and test it without the interfaces that can be mocked.
- Sometimes we are interested only in one method of the other class and we don’t want to be bound to single class that implements this method, and we want to replace that method implementation. In order to reduce the knowledge about the other class to single methods signature we can use delegates in C#, functional interfaces in Java, Kotlin or function pointers in C\C++. Not all OOP languages provide such constructs though then we should use more verbose interfaces or abstract classes. A delegate can bee seen as placeholder for a method. And once we start to focus on a method without accompanying class we start to enter the realm of Functional programming where function implementation can be written as lambda expression (anonymous functions) and its return type and arguments can be other functions. The most common areas where the function placeholders are used are events and callbacks. And once Linq came out everyone who got to know this library really started to appreciate lambda expressions
- In cases where Interfaces and Anonymous methods are not enough to describe dependency, for example we don’t want to restrict a method description in our execution flow with a single signature and want to use different rules to describe the method or a class that contains the method, then we can use Reflection. Although Reflection is very powerful tool that allows to achieve a great flexibility, usually it is not recommended to use because it adds an overhead at runtime and degrades the performance
On the larger scale where components are not anymore single classes but the whole systems the loose coupling further can be achieved by introducing the middle-ware like Queues and Service Buses.
As we can see making a method call something that is not bound to a single implementation opens up a dozen of options how to design and build an application in very flexible way.
P.S. Visit http://fitradar.me/ and join the mailing list!
Recently our team finished the work on FitRadar booking system. That was quite a challenging task and I decided to share some insights and knowledge we gained during the design and development of this system. Already on the early stage of designing and requirement gathering it was clear that ticket booking system on the back-end should be independent from the rest of the Fitradar system because we wanted to introduce Event Sourcing for such entities as Order and Payment. Since these two entities are responsible of money charging and money is always a very sensitive topic, we wanted to make sure we can always track down the state changes in booking and payment processes. But to what degree it should be independent was the question we had to answer.
- fault in one object might lead to crash in another object
- the load of a single object affects the whole process, so we can’t assign PC resources to separate app components. It means you can only scale the whole application, usually by creating a new instance of the application. This starts to play a big role when app is hosted on cloud environment like Azure, Google Cloud or AWS where we must pay for used resources.
- It is hard to apply new technology or framework to the new feature. Usually the whole application is build based on single architectural pattern like MVC and CRUD or MVC and CQRS and it is hard to introduce one more pattern (if we already using simple Data Access Objects for working with data coming from web, then it will take some time to introduce CQRS with Event Sourcing) in the same application. It is much simpler to create a new application.
So there is very little we can do about object decoupling at runtime in single process application case, but do we really need to deploy a booking system in a separate application? Maybe we can just isolate our booking system in a separate library and still run it in the same process with the rest of FitRadar libraries? And so we started to investigate it. Very quickly we noticed that our ideas of making booking system independent from the rest of application strongly reassembles the principles of Microservices architecture . And since now days there are a lot of talks around the Microservices we thought that our project might be a good candidate to move to Microservices architecture. But just because something is promoted doesn’t mean it fits your needs. You usually don’t start the development of application as a distributed system, unless it was a requirement from the beginning. Applications usually mature to the state when Monolithic Architecture doesn’t satisfy the initial requirements and a team starts to consider switching to Microservices Architecture. And we wanted to make sure that this is the time when the new feature requires us to switch to the new Architecture to make the development easier in the future. Here are the advantages of Microservices Architecture that really attracted our attention:
- it gives us a smaller code base to work with. It is a really huge benefit if you consider that at certain point a team more and more starts to think about how properly structure the project (how to write the Clean Code), that any new developer could easy understand it and navigate it. And putting a Booking system as a separate solution would allow as to reduce the code complexity and as result would allow developers navigate faster and add new code faster. If you have ever worked on enterprise scale application development then you know how much time it can take just to figure out where to put your new code.
- Web API end to end tests and Integration tests can run much faster because there is no need to load all of the Fitradar system libraries only those related to booking system. This advantage really starts to shine when we enter the test phase.
- It allows us to scale booking system and the rest of the back-end application independently. The booking system is more focused on data writing in the database on the other hand main back-end application is focused on data serving. We expect thousands of data requests a day while user will be navigating around in mobile application and just few bookings a day.
- Improved fault isolation
And for our project it seemed that we will gain more than loose if we will treat booking system as separate application and deploy it in a separate process. So we gave it a try.
Visit our website: http://fitradar.me/ and join the mailing list. Our app is coming soon!
One day I was listening interview with a person who was running software development courses, he was answering questions regarding the software development in different fields and what a full stack developer means. And since our Fitradar system covers several development fields I decided to share my experience about working in one or another field and how easy is to jump from one domain field to another one.
I remember back in a day when I was still a student at university several classes were focusing on business modeling and system implementation according the model. As later I found out this was a common approach for enterprise application design and development. But my first job related to software development was in the company that produced routers and its software. At that time I was writing small scripts to test different router configuration setups, I was not directly involved in router’s software development but I wanted to become a par of a development team. And so I started to explore the routers operating system which was based on Linux kernel as many other embedded systems. I soon discovered that many principles I learned in programming classes are not applied in embedded systems and instead big emphasize is put on performance. For example instead of throwing exceptions error codes were used to improve the performance. In mobile and enterprise applications that would be considered as a bad practice. Another odd thing for me was to see that there are no unit tests only integration or end to end tests, which again in enterprise application world would be considered very bad. And so at that moment it hit me that the way how one or the another system is developed depends from the domain field and not that much on the language. So for myself I distinguished following software development fields:
- web front-end development
- mobile application development
- desktop application development
- game development
- embedded systems development
- enterprise application development
This is by no means the full list of the domain fields where the software is developed. These are just areas I have come across in my developers career. There are many principles that cover all the fields and that is what every programming class starts with, like variables, loops, conditions, functions, but once we need to organize bigger code base the principles start to vary. In our Fitradar project we are developing two big applications: mobile application for Android and iOS and back-end system that gradually evolves in full scale enterprise application. The approaches in some parts of both systems are similar but some parts have quite different goals. So in this article I wanted to sum up the differences and common things approaching the mobile app and back-end app development in Fitradar solution. As mentioned earlier those differences really start to show up when the code base starts to become so big that you need some extra time to navigate within it. And if you don’t follow any code organization principles the time you will need to navigate around, understand and modify will grow proportionally and sometime even exponentially to the size of the code base. So for big systems we really need to organize our code. And almost all my previous articles about development were dedicated to the different approaches on how to better organize the code. The one thing I discover again and again is this – although it is important to know the principles like Object Oriented programming, SOLID and design patterns but just as important is to apply those principles only there where is needed. I remember one web project where front-end part was developed in Angular but back-end in ASP.NET MVC. Our team took over the project from the other company and had to continue to extend it with new features. When we worked with back-end part it was easy to understand and modify it because it followed well established enterprise application best practices. But we really struggled with front-end part because the code was organized according the same principles as in a back-end part and it looked like developers were ignoring many Angular built-in features and principles. And only later we found out that the developers who mainly worked with back-end designed the front-end application as well. This approach would have worked fine if the front end had been very simple application but it was so big that in order to organize the front-end code it required a knowledge of principles specific only to User Interface. And from my experience for a developer new in a domain field to start to produce decent design takes about a year and more, not counting the time needed to master the programming language itself. So therefore for big web application projects there are usually front-end and back-end developers. For smaller web applications the same knowledge about the programming might be enough. So let’s see where the focus in back-end and mobile application lays in:
- as you can imagine even the simplest mobile app has an UI (there are some special background apps but we will not consider them here) and therefore the emphasize in mobile application in first place will be on the UI code organization and how to connect UI with the rest of the application. The UI will be the part of the system that takes the input from a user and displays the information to the user. From the other hand back-end interaction with the outside world will be via REST (or maybe GraphQL) web services where data is received and send in well formatted way. And formatting usually is done by back-end third party library. Since UI can be very complex then we need to consider principles, practices and patterns that are specific only to UI development. And that is where pure back-end developers lack the knowledge. And if no data is used then mobile app might be limited just to UI and for back-end developer that would mean that very little knowledge can be transferred from back-end development. But in case mobile application works with data stored either locally on mobile device or on a back-end server the extra layer of data persistence might be required.
- Data layer development in mobile app and on the back-end might seem very similar. And indeed if we choose to store data on a mobile device we can chose database for this purpose and use the well known patterns like Repository and Data Access Object as we do on the back-end server, then it might give the impression that mobile app developer can develop this part of the system for both mobile and back-end application. But my experience shows that it is true only to some extent. On the mobile app data persistence layer always should be simple, because the hardware resources are very limited and it is unwise to build large scale database on the mobile device, instead data are transferred to back-end server and stored there. Database on mobile devices often is used as a cache store, where data are denormalized and structured purely for UI needs. On the other hand the back-end database design is a big thing where data normalization and performance is considered. And this time pure front-end developers might lack the knowledge of complex persistence layer design.
- And when the system’s complexity grows more layers on the back-end start to emerge, like Domain layer and Event Bus. Inner details of Domain logic usually is something that people don’t want to expose to the outside world therefore it is implemented only on a back-end server. Domain logic implementation might require a lot of specific design patterns and practices. Which again only back-end developers might be aware of.
So at the end of the day we can still apply general software development knowledge across the domains as long as the code base stays small and simple. And that is why even high school student can produce decent software in any field as long as that peace of software is small. But once the system grows big particular domain expertise starts to become crucial, and that domain expert knowledge comes only over the years as a result of learning and practice.
Please visit our website: http://fitradar.me/ and join the mailing list! Our app is coming soon.