La programmation orientée objet (POO) est un concept conçu pour faciliter le développement de systèmes complexes en introduisant de nouveaux concepts plus proches du monde réel que les langages de programmation fonctionnels et procéduraux. Comme l'écrit Wikipédia, «le langage humain ordinaire dans son ensemble reflète l'idéologie de la POO, commençant par encapsuler l'idée d'un objet sous la forme de son nom et se terminant par le polymorphisme d'utiliser le mot au sens figuré, qui développe finalement l'expression de la représentation à travers le nom de l'objet vers un concept à part entière - une classe.

Mais du point de vue de tous ceux qui ont découvert ces abstractions pour la première fois, après les langages procéduraux classiques, cela n'est pas devenu plus clair, il semble au contraire qu'il était encore plus confus.
D'autre part, il existe des notations graphiques du programme, qui ne sont pas proches du langage humain, mais sont beaucoup plus compréhensibles que même n'importe quel code, pas comme la POO. Il est possible que cela soit plus clair pour moi, gâté par une formation d'ingénieur, mais il y a beaucoup de gens comme moi et ce texte pour les mêmes physiciens gâtés qui ne comprennent pas les abstractions élevées.
Voici, par exemple, une vraie description dans la notation graphique de l'algorithme de contrôle de vanne à vanne NPP:
Figure 1. Exemple d'un programme de contrôle de centrale nucléaire en notation graphiqueA gauche, les signaux d'entrée, à droite, les commandes.
Il me semble que même un enfant peut lire un tel algorithme:
- Si la pompe est allumée pendant 60 secondes et que le débit est inférieur à 10, ouvrez la vanne de recirculation.
- Si la pompe est allumée, donnez l'ordre d'ouvrir dans les 5 secondes aux vannes 001 et 002.
- Si le débit est supérieur à 20 et que la pompe est allumée, puis dans les 5 secondes pour envoyer à la vanne d'obturation 003 une commande de fermeture.
Lorsque j'étais étudiant, je travaillais à temps partiel en créant une bibliothèque de composants pour Delphi et connaissais bien la POO. Puis, lorsque je suis tombé sur de vrais programmes de contrôle de centrales nucléaires, j'ai été très surpris qu'il n'y ait pas d'abstraction, d'encapsulation et, pardonnez-moi, de polymorphisme, uniquement du C pur, et de la recommandation de MISRA C qui a été réduite par les règles afin que tout soit fiable , portable et sûr.
Le pic de coupure de C dans ma pratique était FIL, pour les systèmes de contrôle du réacteur RBMK. Dans celui-ci, les fonctions étaient pré-écrites en C, compilées, puis appelées sur la base d'un fichier texte, où elles étaient décrites dans le langage FIL. En conséquence, il n'a été possible d'appeler qu'un ensemble de fonctions limité, mais soigneusement testé et débogué. Et tout cela au nom de la sécurité et de la fiabilité.
Mais en même temps, le système de contrôle du réacteur et le système de contrôle de la centrale nucléaire dans son ensemble sont juste le cas où les principes de la POO devraient être appliqués à leur plein potentiel. En fait, il existe de nombreux équipements similaires - vannes, pompes, capteurs, tout est facilement classé, il y a des objets prêts à l'emploi qui correspondent à un équipement réel. Il semblerait que la voici: utilisez la POO, les classes, l'héritage, l'abstraction et le polymorphisme. Mais non, vous avez besoin de C pur et ce sont des exigences de sécurité.
Et puis - encore plus intéressant. En fait, le programme de gestion de la centrale nucléaire n'est pas écrit par le programmeur, mais par le technologue - lui seul sait quoi et quand fermer, ouvrir, allumer, et surtout - il sait quand éteindre le canoë, pour ne pas tomber en panne. Et le programmeur doit implémenter soigneusement tout cela en code C. Et encore mieux, qu'il n'y aurait pas de programmeur du tout, et le technologue lui-même a dessiné les algorithmes technologiques des programmes de contrôle sous forme graphique, généré automatiquement du code C et l'a chargé dans l'équipement de contrôle. Les normes de sécurité internationales le recommandent; dans ce cas, un programmeur - comme un violoniste - n'est pas nécessaire. Il n'introduit que des erreurs et distorsions supplémentaires dans la mise en œuvre des réflexions du technologue.

Quelle a été ma surprise quand j'ai découvert que les technologues et concepteurs de NPP, indépendamment des programmeurs, ont développé et utilisé avec succès la programmation orientée objet, et même dans les notations graphiques, mais le code résultant répond pleinement aux exigences de sécurité et ne contient pas d'artefacts de la méthodologie OOP .
En fait, si vous regardez le code généré à partir du circuit de la figure 1, nous verrons du C pur sans aucune classe.
Par exemple, la table d'entrée d'algorithme:
state_vars->kbaalgsv0_out_1_ = kba31ap001_xb01; state_vars->kbaalgsv0_out_4_ = kba31cf001_xq01;
Assigner simplement des variables.
Tout bloc est décrit comme calculant la sortie par entrée, en tenant compte des paramètres spécifiés dans la liste des constantes. Par exemple, le bloc "Plus" ressemble à ceci dans le code:
locals->v5_out_0_ = state_vars->kbaalgsv0_out_4_ > consts->kbaalgsv3_a_;
La sortie de bloc est le résultat de la comparaison du signal d'entrée avec une valeur dans une constante.
Ainsi, dans d'autres blocs, les variables locales des variables d'entrée sont calculées séquentiellement et à la fin du cycle de programme, les variables sont écrites dans les variables de sortie.
if((action==f_InitState)||(action==f_GoodStep)||(action==f_RestoreOuts)){ kba31ey001_yb01 = locals->v8_out_0_; kba31ey001_yb11 = state_vars->kbaalgsv9_out_0_; kba31ey001_yb12 = state_vars->kbaalgsv12_out_0_; kba31ey001_yb02 = locals->v13_out_0_; };
Où sont les cours ici, demandez-vous?
Toute la méthodologie liée à la POO est en noms de variables. Il semblerait que cela pourrait être dans le nom de la variable? Et il peut y avoir tout un abîme. Par exemple, le nom de la variable est kba31ap001_xb01, juste une variable en code C qui répond à l'exigence pour le nom des variables. Cependant, pour un ingénieur d'études, cela ressemble à ceci: «Compartiment réacteur, système d'alimentation en eau industrielle, première pompe, démarrage». Toute cette magie de conversion se produit grâce au merveilleux système de codage allemand (Kraftwerk-Kennzeichensystem) KKS, citation:
«Ce système de classification de codage est conçu pour les centrales électriques et a un grand potentiel, et prend également en compte les caractéristiques du matériel de microprocesseur librement programmable.
Outre le marquage des équipements technologiques, des organes exécutifs (vannes d'arrêt, de sécurité, d'arrêt, etc., mécanismes auxiliaires), des points de mesure, des unités de montage, des dispositifs d'automatisation, des bâtiments et des structures, le système KKS permet de marquer des algorithmes et des programmes de différents types. et finalités (algorithmes de traitement des paramètres technologiques mesurés, signalisation, régulation automatique, protections technologiques, contrôle logique: verrous, ABP, programmes pas à pas, - calcul de t indicateurs hniko-économiques et le diagnostic des équipements technologiques), entrée, sortie et les signaux intermédiaires d'algorithmes et des programmes, des enregistrements vidéo de tous les niveaux sont affichés sur les terminaux vidéo, câbles, etc ... "
Mais le plus intéressant dans la dernière partie du nom est _xb01 , qui est spécifié par le trait de soulignement. Si vous regardez la base du signal pour le projet de gestion, nous y verrons des cours compréhensibles et familiers à tous ceux qui, une fois, quelque part et quelque part, étaient intéressés par la POO (voir Fig. 2).
Figure 2. Exemple de structure de base de signal pour un système de contrôle de centrale nucléaire.Nous avons des classes, ou des tableaux, dans la figure c'est la colonne "Catégories". Par exemple, "KD1" qui a une table de signaux de modèle, des champs de la classe Limite de mesure supérieure, limite de mesure inférieure, lecture du capteur , etc. Est une abstraction.
Et il y a aussi une implémentation de cette classe - un capteur spécifique, par exemple, TK21F02B1, situé dans le circuit, comme vous pouvez le deviner d'après son nom, dans le "compartiment du réacteur, système d'alimentation en eau industrielle, à la première pompe", et le fait qu'il s'agisse d'un capteur de débit est dans ce titre, mais ce n'est pas exact.
Et cette instance de cette classe a des signaux spécifiques et leurs valeurs, dans le processus du programme, et ils sont accessibles par les noms des champs de la classe. Par exemple, une lecture de capteur est indiquée par la variable TK21F02B1_XQ04.
À ce stade, nous pouvons dire, attendez, ce n'est pas du tout OOP, ou même pas du tout, c'est juste une structure de données, c'est en standard C. Et où est l'encapsulation des méthodes dans la classe? Le traitement des données devrait être dans la classe, alors ce sera la vraie méthode POO casher.
Voyons à quoi ressemble le sous-programme de contrôle de fiabilité du capteur sous forme graphique. La figure 3 fait partie du circuit de traitement du signal:
Figure 3. Un exemple de programme de traitement du signal.On peut voir que dans le sous-programme de traitement, les noms de variables TK21F02B1_XQ04 sont utilisés, formés selon les règles KKS et basés sur la table de champ de classe. Dans l'exemple ci-dessus, les lectures du capteur sont calculées en pourcentage TK21F02B1_XQ03 en fonction des valeurs définies des champs de l'instance de classe telles que TK21F02B1_Xmin et TK21F02B1_Xmax.
Si nous nous tournons vers le code généré à partir de ce schéma, nous verrons une simple affectation d'une valeur à une variable, C pur et pas de plus et OOP.
state_vars->su100v12_out_0_ = tk21f02b1_ai;
Et affectation du résultat du calcul, également comme une simple affectation d'une variable (avec vérification de la validité du nombre, afin de ne pas faire tomber le système si nous recevions une erreur suite au traitement du signal)
if(isfinite(locals->v63_out_0_)){ tk21f02b1_xq04 = locals->v63_out_0_; };
Et à quel moment apparaît l'union de ces champs de la classe des méthodes de traitement? En fait, je connais deux options pour cette orientation. Nous allons maintenant analyser l'un d'eux. (La deuxième option est analysée ici .. )
Voyons comment le bloc dans lequel se trouve le circuit du programme de traitement est configuré sur le schéma (voir Fig. 4).
Nous avons un circuit sur lequel nous plaçons des blocs d'un sous-modèle d'un langage de programmation graphique; à l'intérieur de ces blocs se trouve un circuit graphique, dont une partie est illustrée à la figure 3, un programme de traitement des signaux des capteurs.
Dans les propriétés de ce bloc, nous voyons les champs de la base de données de signaux et une liste déroulante qui contient des signaux déjà existants dans la base de données, des instances de la classe, des capteurs spécifiques de ce type. Il suffit de choisir le capteur souhaité, une instance de la classe par son nom, et un miracle se produit. Dans le schéma, tous les blocs de lecture et d'écriture reçoivent des noms de type TK21F02B1_XQ03 (nom de capteur d'instance de classe + nom de champ).
Maintenant, lors de la génération du code C, toutes les variables recevront les valeurs du capteur souhaité. Et le programmeur n'est pas nécessaire, le technologue a tout fait lui-même quand il a développé le schéma dans le langage de programmation graphique pour l'algorithme de contrôle NPP.
Figure 4. Exemple de configuration d'un circuit de traitement de capteur.Pour attribuer des noms, un script d'automatisation spécial est utilisé dans l'environnement de conception du système de contrôle, à peu près le même que dans la figure 5. Tous les blocs de lecture du diagramme se voient attribuer des noms composés du nom de l'objet et du nom du champ dans la classe (voir figure 5).
Figure 5. Définition du nom des variables dans les blocs de lecture.Il est clair que de la même manière, un nombre illimité d'options de traitement du signal peut être créé, essentiellement des méthodes pour la classe dans la méthodologie OOP. De la même manière, elles peuvent être formées pour le capteur, son résumé lorsqu'il est affiché sur les images vidéo du système SCADA, ou par exemple, le traitement des procédures de modification des paramètres. Un diagramme est créé sous forme graphique, enregistré sous forme de bloc et utilisé si nécessaire.
Pour résumer: dans les langages de programmation graphique, les méthodes POO sont également utilisées et sont avantageuses. Et après avoir généré le code source des programmes de contrôle, tous les artefacts de la méthodologie OOP disparaissent et restent propres C, sûrs, fiables, vérifiés.
Il est clair qu'une telle application d'outils d'automatisation, en plus d'accélérer le développement, peut également réduire considérablement le temps de développement, le nombre d'erreurs dans les programmes de contrôle.