What happens inside the program is very similar to the activities of a team of several people. Each team member has his own task and, most likely, his own “workplace” to which no one except him should touch. Colleagues can give each other instructions and transmit some information about the work process. They can ask each other for help and can provide it. Like any team, they have a boss whose task is to interact with the user and coordinate actions within the team.
With this view of the program, it comes to life, and everything that happens inside it begins to take on some kind of image. Having distributed all the work processes and tasks among the various “employees”, you begin to understand how everything should work.
The source code of the player, which I once spent a lot of time on, has long been gathering dust on the hard drive. I wrote this application for a year when the mood appeared. In the end, my enthusiasm ran out and the player was forgotten. And recently, I came up with the idea of architecture, which, as it turned out, fits perfectly with it - we will talk about it later. I will highlight the “workers” in the application, and distribute the roles so that each employee has a clear, simple, and understandable task.
To begin with, the most important member of the team is the singer. He bawls songs on the notes that palm off on him. Naturally, no notes are processed in the program - this is just a replacement for the concept of “music track”. The singer can be instructed to sing something, ask to stop, and ask to sing a little louder or quieter. You can also put the singer the notes of the next song on the list so that he quickly moves from one song to another.
While the singer is yelling, someone should keep a list of songs that will be sung next. This is where the sorter comes in. His task is to maintain a list of the songs to be played further in accordance with the playback mode pleasing to the user. When the singer finishes the song he asks the sorter to give him notes from the next. And he either gives them, or shrugs, saying that the list has ended, and there is no repeat. In addition, at any time, the boss can inform that the user has changed the playback order, and the sorter will have to create a new list.
The sorter only stores the playback order and he needs to know what songs are available at all. For storing a complete list of songs and manipulating it, an audio technician is responsible (it seems there is such a word). Most often, it is the sorter who refers to his services when compiling his list. The audio library can give a list of root folders, a list of the contents of each folder, and information about any track in the audio library.
There is one more task. When the user adds a new music folder to the audio library, this folder must be viewed and the information about all found music in the audio library must be entered. This could be done by the audio library, but in this case it would be difficult to ensure the simultaneous scanning of folders and the correct functioning of the audio library. Let the search engine do this - it will accumulate all the changes that need to be done and transfer them to the audio clerk in one fell swoop in order to minimize delays when working with the audio library to a minimum.
And the last, most responsible character is the boss. He is responsible for starting the work of his team and for interacting with the user. It controls the interface and lets the rest know if the user wants something. A pause button is pressed - the boss asks the singer to stop. A composition has been added to the queue - the boss reports this to the sorter, and so on. In our case, this is most likely not needed, but subordinates can also contact the chief if they need help in something that they themselves cannot handle. In this case, the boss can show who in the team can help.
Who are all these people?
I have never heard of such an architecture, but there is a chance that something like this already exists. If you heard about this - I will be grateful if you write about it in the comments. Despite the fact that I may have invented a bicycle, I won’t stop - it suddenly turns out to be a mountain bike.
Let's get back to business. We must somehow name the performers. I thought about workers, personalities, and minions, but I think the most appropriate word would be "character." This term is impersonal enough to call them and anyone. And the loafer and the nurse and the main villain. What should be the character?
Firstly, he must have some freedom. The same as people in real life possess. You cannot force your employee to do something with the help of physical strength (I am for humane labor). Therefore, you can’t directly call the functions of the character’s object - it would be like “puppetry,” rather than voluntary work. Instead, he should receive messages and respond to them whenever possible. It turns out that messaging methods should be provided.
Secondly, a stream should be allocated for each participant in the process. This will ensure their independence from each other.
Thirdly, so that the streams do not spoil the data while accessing them, it is necessary to provide appropriate means. This is somewhat similar to the interaction of processes in the system and the problems existing there.
The character sequentially processes messages arriving to him. If there are no messages, it may be idle or do some background work by periodically checking the message queue.
What should be the messages? You can make one single type - universal, which can be used in all cases by setting the necessary parameters. About the same as there is a universal concept of function. But I try to avoid such decisions, since universality often complicates the implementation of simple actions. I prefer three simple methods covering all possible options for performing some action, to one complex universal one. This, of course, somewhat complicates learning how to perform this action, but at times speeds up its application and improves the visibility of expressions. In addition, if the actions are divided into types, this means that the machine can easily distinguish between them, and this, in turn, expands the possibilities of automation and optimization.
So, offhand I can break the messages into three groups:
1) Tasks / assignments - someone wants the character to do some work. Example: when the user presses “play”, the boss asks the singer to start performing the song.
2) Requests - the character may ask his colleague to convey some materials to him. When the person requested (such a word should be) is ready for transmission, the applicant will receive a message from him with the necessary materials. Example: when a singer needs a new composition, he asks for it from the sorter.
3) Notifications of events - it may happen that the activity of one character will depend on the actions of another. The commander needs to know when the singer changes the song to update the interface. For this, the commander needs to ask the singer to inform about the change of song. And the singer, in turn, will send out notification messages to everyone who asked about it.
Along with messages, you can transfer any materials or parameters. In fact, the only difference between sending a message and calling a function is that messages are sent to characters and can be delayed while functions are triggered immediately and relate to objects.
Then I thought to paint all the messages that every character of the player understands, but the list was pretty big and I decided that it was pretty useless. So I will begin to finish.
The presented architecture allows you to quite clearly present a multithreaded application. In addition, the breakdown of all components of the program into objects and performers makes the structure of the program more visible. With team development, it becomes clearer how to share responsibilities - each programmer can take on a character.
It turns out that the program is just a room with several workers and working materials. A programmer’s dream came true. I can explain how the program works. I am sure that if the concept is easy to imagine, then it has a chance.