2

I have a project that has a DD design, and also uses dependency injection. During development, we connect to a test database which contains a former snapshot of production. This works well 95% of the time. However, for some processes that we have to implement into our application, the underlying SQL statements, (of which I can't control and are developed by a third party) are slow. Some of these procedures can take 30 seconds while even others might take over 5 minutes to execute.

Our UI's rely on this data and, unfortunately, our users understand that there are some tasks they have to start and just wait for the data to arrive. For now, I'm not asking for ways to speed up the final application. Simply put, there are just to many factors outside of our control and this limitation has to be accepted as part of the final result.

However, while developing the UI I do require a responsive return of results from my domain. To do this, I've setup fake repositories within my application project. Specifically, I have an ASP.Net project that initializes all of the DI components within the AppHost. It is hear that all repos are injected into the container, followed by the respective domains, which are then used by the ASP.Net APIs that are utilized by the web page UI.

So far, what I've done has been to create fake repositories from within ASP.Net project. Within the AppHost, I have an #ifdef FAKES preprocessor that checks to see if I've specified that I'd like to use the fake repos, and it then loads the fakes, rather than the legit ones which are used during normal testing and eventually production.

This work but feels... wrong. Maybe this is the correct approach, but I feel as if there has to be a better way of injecting fake data repos into my application for development. Is there a better appraoch for this purpose?

One requirement is that I do not want to always access this faked data in development. While building UIs, I often could care less about what the data looks like, so long as something is there that has the right data types and string lengths. However, once it's time to test implementation, I will always have to wait for the legitimate test data to load from our test servers.

Just to be clear, these fakes are not for unit testing. In this context, I am strictly creating fake repositories so that I'm getting data back in milliseconds, rather than 2-3 minutes. Is there a better way of implementing and loading these context-specific development fakes?

2
  • can't you have a second test-database which is less "full"?
    – Pieter B
    Jan 29, 2020 at 12:26
  • @PieterB Anything is possible with enough time and money. To answer that question in that context... honestly, no.
    – RLH
    Jan 29, 2020 at 14:48

1 Answer 1

2

Given the feedback that you provided, then the use of fakes is entirely justified. Given the desire to be able to quickly switch between the fakes and the real data, you may want to make the use of the fakes driven by the existence of a DLL.

The solution would look like this:

  • Create an assembly to contain the implementations for your fakes.
    • Interface definition and common model code should live in a root assembly
    • The fakes assembly would reference that root assembly
    • The actual implementation assembly would also reference the root assembly
  • Check if the assembly exists in the application directory at run time
    • If it exists, set up the DI container to use the fake

You can put the whole dynamic loading functionality inside a #if DEBUG section of code, so it doesn't slip into production. Alternatively, you can make the choice of which assembly to load be a parameter that is read after the application is launched. That will allow you to quickly and easily swap out fakes without recompiling.


Original answer which is still valid for smaller systems

There are two things I recommend you do:

  • Get a DBA to figure out if you need to add indexes, the right indexes can improve the speed of a query by several orders of magnitude
  • Set up a test database with the minimal set of data to put the UI through its paces, so the queries run quickly even if it is not optimized

When you need the fast response times, connect to the minimal database. When you need to validate the correctness of the application, connect to the backup of production.

While you may not be in control of the queries, you should be able to influence the schema. Using the backup of production, you can judiciously add indexes to improve the performance of the queries. If the performance is sufficiently improved, get it pushed to production.

5
  • Regarding the DBA bit. I could do that, but this is part of a HUGE ERP system and as per the terms of the system, it runs on our servers but we don't touch it. The 3rd party does. And there's a lot we'd like to get them to improve, but we can't fork out millions of dollars to get them to do that.
    – RLH
    Jan 28, 2020 at 17:35
  • Regarding point #2, again, this is a HUGE ERP system that spans multiple warehouse and locations. There's not just a lot of data in tables, but there are hundreds of tables. Setting up a new, empty schema isn't possible as there is way to much data that is need and needs to be properly created. Unfortunately, a lot of that flow and logic is built into their front-end application, so we can't even fake it. This is why we use production snapshots in test.
    – RLH
    Jan 28, 2020 at 17:37
  • You can present recommendations though, can't you? If they are charging millions to add an index that is a big problem. Given the new information and the inflexibility of the 3rd party, your use of fakes for development seems quite reasonable. Jan 28, 2020 at 20:56
  • Oh, we can and do present recommendations. We've even done the big "no nos" of modifying the DBs when it was just unacceptable performance. We have a good relationship with the company that owns ERP software, but we're not their biggest customer. Also, I like your answer. My current define statement is #if DEBUG \n #define FAKE\n #endif. Then, if I want to use the legit test DB, I comment out the FAKE definition. I considered moving the fake code to another assembly. I'm not 100% sure our DI engine supports dynamic loading of assemblies, but I'll look into that. Thanks!
    – RLH
    Jan 29, 2020 at 14:41
  • @RLH, you might have to build that in to your startup code yourself. I.e. perform the Assembly.Load() call to make the implementations available. I do something similar in my DHaven.Faux project (uses net core DI services): github.com/D-Haven/DHaven.Faux/blob/develop/DHaven.Faux/… Jan 29, 2020 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.