A miracle has occurred! I implemented few things for Commutee and that is great! 🙂
It is not some kind of breakthrough, but it is a progress, and that counts as a success! Last time I wrote about general architectural design, using hexagonal architecture, also know as ports and adapters. This week I started implementing this design. I must say that it was a pretty good feeling, it all comes together pretty nicely. There is still a lot to do, for example, I am thinking about using the same architecture for timetables fetching and parsing module with the idea, that in the future, I will separate it into a completely separate application – microservice! But for now, it will be just one big, fat, adapter that periodically will fetch the data and push it into the core domain using one of the ports.
Currently, I have finished the core data loading part, that is getting the data from outside source, port, and pushing it into the database and that is also some other kind of another port – a database port. I also wrote some tests that check if this logic works correctly. But you may ask, how can I test pushing data to the database without having a database? Yes, I can’t test this without a database. But what if I would just mock a database? I have the interface for the database, so I could just use Mockito, generate mock, setup few rules with when and then methods that would that would simulate the behavior of real database and just write tests with that. But after few tries, I tried a different approach.
My own database
Yes, I wrote my own, in memory database. It sounds scary, but it is super simple. As I had the interface, I just created an implementation of it, generated all the methods and placed this class in the test sources so it would be only available in tests. As the data store of this "database", I have used a simple HashMap, yes, with a String as a key, and some object as value. Simple as that.
I could use this approach because my interface was really simple, it does not have any complicated query mechanism, that would require a real database, it really is a simple key-value store, a hash map.
Of course, this is risky, as I can create some bugs in my database implementation that will generate false positives in tests, but since it is really simple, methods are few lines of code at most, it is really easy to debug without writing tests for this database. And as a side bonus, this solution is blazing fast, there is no need to boot up some real database, it saves a lot of time.
Some of the interface methods, defined relations between few objects, for example, a connection required two bus stops. My first approach was to create a Map of Maps so that in the first map, first bus stop would be a key, and in the inner map, the other one would me a key. It sounded simple. But it was not, do not do this! This creates really complicated code in your in-memory database implementation, methods become pretty long, there is a lot of logic involved, a lot of checks. This generates errors. A simpler solution is to generate some compound keys for a single map. In the above example, I just generated string that consisted of two, joined bus stop IDs. This simplified my code tremendously and made it easily readable and easy to debug if I needed to.
You can check the complete implementation of this database in Commutee repository at GitHub