Choosing a "big" project
As I am following Open Source Science University cursus to strengthen my weaknesses in software development (namely engineering and architecture), I also try to maintain a "bigger" project for my portfolio, and also with the objective to finish a piece of software I'm proud of.
I could have tried the more classic projects (making a text editor or a LISP or a bash shell are common "big projects" I've seen), but I was kind of afraid of the perceived complexity of those, so I preferred looking for something that started as a small project and then can get bigger as features come. This is how the idea of emergence came to life.
The idea to run flocking/experiments for a serious program came from a small presentation seen on Tech.io named Flocking Autonomous Agents. The main logic units do not seem to big to create (and tests) and we can add a lot of features on top of this to run a (hopefully) full fledged ant colony simulation.
First blind try with Qt
The repository for my first attempt can be found on github. On this first try I was really concerned with the UI, because I never worked from scratch on a GUI application. The strong compatibility of Qt with multiple environments, as well as having a KDE desktop environment naturally made me try Qt as a GUI library.
I reached the point I marked as minimum objective : display multiple agents - ants - on the screen and having all these agents autonomously make decisions about where they want to go, given what they see. I also want to enable the possibility to create a finite size world, because infinite worlds need strong engineering on decision laws for agents, so they don't just drift away in random directions forever. Implementing a finite size world means we need to "wrap around" the world, creating periodicity and taking this periodicity into account for the vision of the different agents.
This first try went good enough, but when I wanted to implement new types of agents and new behaviours for my ant, I met struggle because the inheritance tree between my own types and the Qt Graphics Framework types (namely QGraphicsView, QGraphicsScene and QGraphicsItem) was not clear enough. Therefore I let this project go and tried another approach.
Second try with SDL
This second attempt was motivated by the lack of control over the "game loop" and how objects, and agents are printed on the canvas. Therefore I went to SDL2 for the graphical part of the project, with strong intent to only use standard c++ items in the project and simple API calls to SDL2 for the rendering.
I used the Lazy Foo tutorial to get going on using SDL2 (and I'm not finished yet, this is a big one and I'm catching my backlog on this with only small steps) and then recreated a proper game loop with the transmission of events during the updates. I also reached the same "minimum objective" as I had with the first attempt with Qt, and it was going pretty well, but I thought I needed to come back to Qt. The main reason is the GUI, and the ability to transmit/translate easily GUI events into World events.
The other very big reason for the change, is having watched some videos about design patterns (thanks to Open Source Science University curated list of MOOC) and bought the "Gang of Four"  book. Thanks to these resources, I had a better idea of what each part of Qt Graphics Framework was doing, how and why I should separate the view from the model from the controller (Qt Graphics implementation is very close to Model-View-Controller pattern), and finally it gave me ideas on how to ensure extensibility of my application for new features
|||: (non-affiliated link, I couldn't care less)|
Third try with Qt and design patterns
So for this third attempt (which is the current one), I decided to go back to Qt because of the simplicity it gives in creating a GUI (and I want to be able to interact with the mouse in the simulation in the end), and also because I wanted to focus on the logic and the architecture of the 'Model' part of the program. I can safely leave the other parts to Qt now, and once I am a good client of these libraries, I can start trying to implement more things myself.
The other big addition to this third attempt is structure. Knowing about these common design patterns helped me finding a decent project architecture to begin with, and I was able to put it to paper/images before starting the implementation. This was very important in order to subclass properly the Qt classes into Model classes.
Having an UML diagram for the project made the coding a lot easier. However having too much fun with diagrams almost ended this try : the feature set on the diagram was quite big, and writing code and tests and specifications for a very long time before having any application running is a little discouraging. This is why the "proper specs" file is not filled in now, and probably won't be before a long time.
But with this UML overview always at hand, it is easy to see where the new features would be best added, and if they're possible to add with the chosen architecture for the project in the beginning. I am not sure which features I will add now, but I am pretty sure that this third try will be the (good) last attempt at making an Ant colony simulation, with movement decisions, actions decisions, inter agents, enemy agents, and all the features I thought of when I first read this small playground on Tech.io, even if the new feature additions will come in sparse updates.
Conclusion - takeaways
Design Patterns are a game changer
Learning about the design patterns is probably the first thing I should have done in retrospect, since I already had basic knowledge of programming languages when I really started thinking about trying the IT stuff. Going into an unknown base code/library can be pretty hard, and knowing about these methods really help understanding how and why things are done the way they are.
This is really the "engineering" part I wanted to see when I started looking for resources and I am glad I found it at this timing.
UML diagrams // Doxygen comments is probably enough for now
Documentation is always an issue when starting a project from scratch, especially when it is the first bigger project. I tried to write a full technical specification because I thought it was what I needed to put everything on paper before starting to code, but I felt the burnout coming and decided that it's not worth it for the moment.
On the other hand, keeping a UML diagram and having proper comments in the code (Doxygen style has the advantage of being able to produce HTML documentation and being picked up by a few IDE for informative tooltips) is not very time-consuming and helps tremendously to not get lost in the code. This is the basic level of documentation I should apply to all my further projects until I am convinced otherwise.
Editor / IDE support for live UML updates ?
I am currently using QtCreator for this emergence project, there are a few reasons for this :
- C/C++ does not have a nice Cmake-based LSP implementation I could use in Vim with ale plugin. This is important for unknown APIs like Qt is to me right now
- QtCreator has integrated Qt5 help thanks to its Help Mode, so I can see the documentation while editing
- QtCreator has vim emulation (modal editing feels good each time I remember that I didn't have to reach Control or Alt key to do an operation)
- QtCreator annotations for warnings and errors thanks to Clang CodeModel in real time to avoid wasting time building when I forget semicolons
The only problem I have with QtCreator right now is that I wished it could automatically update the UML diagram I have whenever I edit the code, so the UML diagram is always complete and up-to-date (I'm using PlantUML for the diagram syntax, since it is just a text file and seems to have a lot of integrations). Hopefully I'll find (or write) a plugin or an IDE that handles this properly for me.
I'd like to finish with many thanks to the curators of Open Source Science University and the "Gang of Four" for the help they're providing me and a lot of other enthusiasts with this kind of content.
Have fun, stay safe,