Refactorisation de code - Obtention d'un exemple de codage DELPHI d'encapsulation La refactorisation de code est un moyen d'obtenir une bonne structure. Grâce à la refactorisation, nous pouvons améliorer la qualité du code et augmenter le degré de réutilisation du code tout en gardant les fonctions inchangées. Voici un exemple concret de la façon d’améliorer la qualité du code et d’obtenir l’encapsulation. (L'exemple utilise DELPHI) Fonction de code : Définir un filtre pour l'ensemble de données (TClientDataSet). L'utilisateur peut sélectionner le champ à filtrer dans une TComboBox, puis saisir la valeur à filtrer dans une zone Tedit. Comme le montre la figure 1 : la méthode la plus courante consiste à coder en dur les noms de champs dans notre ensemble de données dans l'attribut Items de TComboBox, puis à ajouter de nombreuses instructions case ou if au code pour déterminer les champs sélectionnés par l'utilisateur. pour définir des filtres pour l'ensemble de données. ...... cas ComboBox1.ItemIndex of0 : ClientDataSet.Filtered := False ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + '''' ; .Filtered := False; ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;... end; Ou utilisez... si ComboBox1.Text = 'Code matériel' alors commencez ClientDataSet.Filtered := False ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True; sinon si ComboBox1.Text = 'name' alors commencez ClientDataSet.Filtered := False; ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;end... Ce code implémente également la définition de filtres pour l'ensemble de données via un codage en dur. répond aux besoins, mais le code ci-dessus est rigide. Si l'ensemble de données comporte de nombreux champs, le codeur doit saisir les champs un par un dans les éléments, et l'ordre doit être vérifié lors de la rédaction du cas, sinon le filtre défini sera erroné et il sera facile pour les développeurs de l'introduire. BOGUE. Il est également pénible de conserver un grand nombre d'instructions if lors de l'utilisation d'instructions if, et cela ne prend pas en charge les changements demandés. Lorsque l'utilisateur demande à modifier le nom d'affichage chinois du champ de l'ensemble de données, il doit également penser à modifier le nom d'affichage chinois du champ de l'ensemble de données. données codées dans les éléments TComboBox. Si vous oubliez, un BUG sera introduit. Ainsi, lors de la première reconstruction, j'ai essayé de charger dynamiquement les données dans TComboBox Items, et en même temps, afin d'obtenir une comparaison lorsque l'utilisateur sélectionne après le chargement. J'ai ajouté un champ privé FFields: array[0..20, 0..2] of string; à ce FORMULAIRE de requête pour enregistrer les données d'informations sur le champ dans l'ensemble de données. Parallèlement, un processus de chargement des données est mis en œuvre : PRocedure TFrmSPARealStorageQuery.GetQueryFields;var i, iFieldsCount: Integer;begin iFieldsCount := 0; with DBGride1.DataSource.DataSet do start for i := 0 to Fields.Count - 1 faites si Fields[ i].Visible alors commencez FFields[iFieldsCount, 0] := Fields[i].FieldName; FFields[iFieldsCount, 1] := Fields[i].DisplayLabel; Inc(iFieldsCount); fin ComboBox1.Items.Clear; (FFields[i, 1]); end;end; Ceci permet le chargement dynamique des informations de champ au moment de l'exécution. Mes paramètres de filtre ressemblent donc à ceci. if ComboBox1.Text <> '' thenbeginClientDataSet.Filtered := False; ClientDataSet.Filter := FFields[ComboBox1.ItemIndex, 0] + '''' + Edit2.Text + ''''; end; Cette méthode augmente sans aucun doute la flexibilité du code et augmente la réutilisabilité du code, car le code est bien isolé des données changeantes. Par conséquent, cela peut être considéré comme pratique tant que vous ajoutez le champ privé FFields: array[0..20, 0..2] of string dans un autre FORM qui implémente également cette fonction et utilisez le processus ci-dessus de chargement dynamique des données. champs définis. La réutilisation est réalisée. Mais cette réutilisation n’est pas très bonne car nous n’avons pas réalisé une bonne encapsulation. Cela conduit à des doublons de code dispersés partout dans votre programme (vous utilisez souvent COPY pour obtenir la réutilisation de cette fonction, car le code ci-dessus n'a pas une bonne encapsulation). Si un jour vous souhaitez modifier la fonction de chargement des données, vous devrez trouver un endroit pour copier la fonction - et vous devrez modifier le code dispersé à d'autres endroits. Je l'ai donc refactorisé à nouveau et encapsulé davantage le code. Le code est le suivant : unit uDataSetFieldsInfo; // Description : L'unité inclut la classe TDataSetFieldsInfo, qui encapsule l'acquisition d'informations sur les sous-segments de l'ensemble de données. // Et fournit une interface de méthode pour afficher les informations dans le champ d'affichage de la liste déroulante et obtenir le nom de la sous-section correspondante // Créé : wuchhao // Date : 2003.5interfaceuses Classes, DBClient, StdCtrls; type TDataSetFieldsInfo = class private FFieldsList : TStrings public constructor; Créer ; destructeur Détruire ; remplacement ; procédure GetDataSetFields(Source : TClientDataSet); procédure ShowFieldsInfo (Target: TComboBox); function GetFieldsNameByDisplayLabel (DisplayLabel: string): chaîne; implémentation{ TDataSetFieldsInfo }constructeur TDataSetFieldsInfo.Create; TDataSetFieldsInfo.Destroy;begin FFieldsList.Free;hérité;end;procedure TDataSetFieldsInfo.GetDataSetFields(Source: TClientDataSet);var i: Integer;begin FFieldsList.Clear; avec Source do start for i := 0 à Fields.Count - 1 do if Fields[i].Visible puis commencez FFieldsList.Add(Fields[i].DisplayLabel); FFieldsList.Add(Fields[i].FieldName); end; end;end;function TDataSetFieldsInfo.GetFieldsNameByDisplayLabel( DisplayLabel: string): string;var index: Integer;begin Résultat : = ''; index := FFieldsList.IndexOf(DisplayLabel); <> -1 then Résultat := FFieldsList.Strings[index+1] ;end;procedure TDataSetFieldsInfo.ShowFieldsInfo(Target: TComboBox);var i: Integer;begin Target.Items.Clear i:=0; .Count commence Target.Items.Add(FFieldsList.Strings[i]); i:= i+ 2; end;end;end. L'unité uDataSetFieldsInfo encapsule les données et les méthodes liées à la réalisation des fonctions décrites dans cet article, et les encapsule dans une classe, réalisant ainsi le principe Open - Close dans la conception orientée objet. La classe devient une boîte noire, elle peut donc être facilement réutilisée (réutilisation de la boîte noire) sans se soucier de la duplication de code. En même temps, parce qu'il encapsule les informations liées à la fonction, les responsabilités de la classe sont clairement définies (responsabilité unique), et il a une granularité suffisante et une bonne encapsulation. TdataSetFieldsInfo isole efficacement la zone de liste déroulante des modifications des données, améliorant ainsi le degré de réutilisation du code tout en réduisant les responsabilités de la classe FORM et la quantité de nombres magiques codés en dur. Voici le nouveau code : Déclarez d'abord une référence à la classe TdataSetFieldsInfo dans le FORM. ...Appelez lorsque FORM est créé : FFieldsInfo := TDataSetFieldsInfo.Create;FFieldsInfo.GetDataSetFields(cdMaster);FFieldsInfo.ShowFieldsInfo(ComboBox1); À ce stade, mes paramètres de filtre deviennent : if ComboBox1.Text <> '' thenbeginClientDataSet.Filtered := Faux; ClientDataSet.Filter := FFieldsInfo.GetFieldsNameByDisplayLabel(ComboBox1.Text) + '''' + Edit2.Text + ''''; ClientDataSet.Filtered := True;end; Obtenir la sous-section correspondante en appelant la procédure d'interface de l'objet FfieldsInfo. nom. Cet article est un exemple simple de refactorisation de code. Je pense que la classe que j'ai implémentée ci-dessus peut être écrite de plusieurs manières et avoir de meilleurs algorithmes. Ceci est juste pour donner une idée sur la refactorisation du code. Afin d'améliorer la qualité de notre code ainsi que sa maintenabilité et son évolutivité, nous explorerons des idées sur la programmation OOD.