Let's talk about what enterprise development is, what nuance enterprise projects may have, and which skills you need to acquire to successfully work within the .NET stack.
Imagine a situation where a business customer comes to you and asks you to make a certain product. And this product must be unique to solve a specific business problem. It should be an integral system with its own development features such as:
The code should be written with the highest quality from the start, using various approaches and patterns, so that the project can be expanded in the future. Since the project will solve certain business problems, you need to prepare to understand and implement complex business logic. Keep in mind,it will evolve, and be supplemented as the project develops. You will also need to delve into the domain area in which the development will be carried out.
An enterprise project is always a matter of money. We cannot afford to use untested solutions. Only frameworks, libraries, and infrastructure services that have been proven over the years are suitable. You can't risk your budgets and rush to the first new service you come across, even if it seems like the best solution on the planet.
Refinement and development of the project are inseparable from constant testing. This approach makes it possible to continuously improve or rework the code over an extended period, while also allowing for the safe updating of older code segments without fear of causing disruptions.The code review process is essential. It helps to catch imperfections and bugs even before they reach the testers, and also to share the knowledge about the developed feature with the team, which can then correct and refine the feature for you.
When writing a project from scratch, we should immediately determine which database is best suited based on the project's objectives.
Logging. It's not enough to just configure it; you need to choose a service that will save logs. Without logging, it is often impossible to understand problems in production, and restoring any artifacts becomes a challenge.
Metrics and health checks. We cannot, having launched a project, forget about the already created part of it while we develop the next one. The service may go down and we won't know. Downtimes always mean financial losses for a business, and they shouldn't happen. To prevent them, you need to proactively, based on business metrics, understand what is going wrong and fix the situation. Developers should learn about bugs and problems in the product faster than the customer.
In addition to logging, it is crucial to provide error tracking or exception tracking and a service that will store errors separately. The tracking service helps group, analyze, and filter errors, track their frequency, provides more detailed information than logs, and quickly sends error notifications. You can integrate error tracking with chats. Custom integrations are also an option, such as the service sending messages about detected errors to developers' phones.
Effective communication between services must be established within an enterprise application: tasks must be completed promptly; the load must be distributed evenly.
The application will need adjustments for deployment. Therefore, the developer needs to understand how the infrastructure will be deployed. For example, deciding on containerization - selecting services and configuring them correctly.
There may be DevOps specialists on the project, but this does not mean that responsibility for the deployment process rests solely with them.
If we have a monolith, we can cache data in memory. If we use microservices with several individual service instances, caching each one in memory becomes impractical. It is unclear how to update them later synchronously. In this case, a distributed cache is the solution: a separate service should be established that stores specific data and provides quick access to it. As a rule, this is a key-value store.
Separate file storages. Why? Because simply storing files on disk is not convenient, and storing files in a database is problematic. Therefore, enterprise projects often use separate file storages as another infrastructure service.
For tasks related to data display, a visualizer should be connected. This makes monitoring metrics and logs and tracking health checks more convenient.
A separate block – code style and analyzers. When the team is already large or medium-sized, everyone can write code differently. This sometimes leads to controversy in code reviews. Therefore, enterprise projects often use analyzers that automatically identify problems, potential errors and ensure a unified code style.
Database:
More advanced level:
In addition to the ability to create tables, think through their architecture, and understand all types of connections and constraints, we also need to be able to navigate different types of indexes: covering, filtering, clustered, non-clustered, composite. This knowledge makes it easier to add indexes to enhance the performance of certain queries at the development stage.
Many queries need to be executed within transactions to avoid inconsistent data in the database.
Enterprise application infrastructure
In addition to all this, it would be beneficial to know how different tools work for identifying problems in the application. For example, a memory analyzer (DotMemory), a performance analyzer (DotTrace), and a database query analyzer (MS SQL Server Profiler).
To implement applications on a microservice architecture, in addition to the knowledge described above, you need to be familiar with microservice interaction patterns.
There are numerous challenges with distributed transactions. It's ideal when you can wrap the code itself in a transaction. However, this isn't possible with microservices because multiple microservices might be involved in a single transaction. In such cases, you have to use the Saga pattern.
Query profiling immediately becomes significantly more complex. We cannot just view all its logs from one service. The entire request, starting from the client, needs to be collected to recreate its path through different services. There are special tools for this.
Collecting logs becomes more challenging.. We don't have one log per sentence, like in a monolith. You must gather logs from various services and potentially standardize them for easier display and analysis.
There is a strong dependence on infrastructure: for example, queues, which everything is tied to, for example. Besides integrating our service with third parties, there is also integration with our own services. And all these potential scenarios need to be managed in a code.
Microservices are significantly more difficult to deploy. We cannot change the API of our service and deploy it in production - services that interact with ours may break.
When one service depends on another, we cannot simply debug our service and expect everything to work seamlessly. We will have to separately deploy another service on which we depend and start debugging in conjunction with it.
It's easy to start working with us. Just fill the brief or call us.