JavaRush /Блоги Java /Random-TG /Биёед синфи StringUtils-ро вайрон кунем
Roman Beekeeper
Сатҳи

Биёед синфи StringUtils-ро вайрон кунем

Дар гурӯҳ нашр шудааст
Салом ба ҳама, хонандагони азизи ман. Ман кӯшиш мекунам, ки дар бораи он чизе, ки маро воқеан ба худ ҷалб мекунад ва дар айни замон чӣ маро ба ташвиш меорад, нависам. Аз ин рӯ, имрӯз хондани сабуке хоҳад буд, ки барои шумо ҳамчун истинод дар оянда муфид хоҳад буд: биёед дар бораи StringUtils сӯҳбат кунем . Биёед синфи StringUtils - 1-ро вайрон кунемҲамин тавр рӯй дод, ки дар як вақт ман китобхонаи Apache Commons Lang 3-ро гузаштам . Ин китобхона бо синфҳои ёрирасон барои кор бо an objectҳои гуногун аст. Ин маҷмӯи усулҳои муфид барои кор бо сатрҳо, коллексияҳо ва ғайра мебошад. Дар як лоиҳаи ҷорӣ, ки ман бояд бо сатрҳо дар тарҷумаи мантиқи тиҷорати 25-сола (аз COBOL ба Java) муфассалтар кор мекардам, маълум шуд, ки ман дар бораи синфи StringUtils дониши кофӣ надоштам . Аз ин рӯ, ман маҷбур будам, ки ҳама чизро худам созам. Ман чиро дар назар дорам? Далели он, ки ба шумо лозим нест, ки вазифаҳои муайяни марбут ба коркарди сатрро худатон нависед, балки ҳалли тайёрро истифода баред. Худатон навиштан чӣ айб дорад? Ҳадди ақал дар он аст, ки ин рамзи бештарест, ки аллакай кайҳо навишта шудааст. Масъалаи санҷиши codeе, ки ба таври илова навишта шудааст, на камтар муҳим аст. Вақте ки мо китобхонаеро истифода мебарем, ки хуб будани худро исбот кардааст, мо интизорем, ки он аллакай санҷида шудааст ва барои санҷиши он ба мо лозим нест, ки як қатор парвандаҳои санҷишӣ нависем. Ҳамин тавр мешавад, ки маҷмӯи усулҳои кор бо сатр дар Java он қадар калон нест. Дар ҳақиқат усулҳои зиёде вуҷуд надоранд, ки барои кор муфид бошанд. Ин синф инчунин барои таъмин намудани чекҳо барои NullPointerException сохта шудааст. Шарҳи мақолаи мо чунин хоҳад буд:
  1. Чӣ тавр пайваст шудан?
  2. Намунаҳо аз кори ман: чӣ гуна ман бехабар дар бораи чунин як синфи муфид, асои велосипедамро офаридаам .
  3. Биёед усулҳои дигареро, ки ман ҷолиб пайдо кардам, бубинем.
  4. Биёед ҷамъбаст кунем.
Ҳама парвандаҳо ба як анбори алоҳида дар ташкилоти ҷамъиятии Javarush дар GitHub илова карда мешаванд . Барои онҳо мисолҳо ва санҷишҳои алоҳида гузошта мешаванд.

0. Чӣ тавр пайваст шудан

Онҳое, ки бо ман даст ба даст меоранд, аллакай каму беш бо Гит ва Мавен шиносанд, аз ин рӯ ман минбаъд ба ин дониш такя мекунам ва худро такрор намекунам. Барои онҳое, ки мақолаҳои қаблии маро пазмон шуданд ё нав хонданро оғоз карданд, дар ин ҷо маводҳо дар бораи Maven ва Git мавҷуданд . Албатта, бе системаи сохтан (Maven, Gredl), шумо инчунин метавонед ҳама чизро дастӣ пайваст кунед, аммо ин имрӯзҳо девона аст ва ба шумо бешубҳа лозим нест, ки ин тавр кунед: беҳтар аст, ки ҳама чизро дуруст иҷро кунед. Аз ин рӯ, барои кор бо Maven, мо аввал вобастагии мувофиқро илова мекунем:
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
   <version>${apache.common.version}</version>
</dependency>
Дар куҷо ${apache.common.version} versionи ин китобхона аст. Минбаъд, барои воридот дар баъзе синф, воридотро илова кунед:
import org.apache.commons.lang3.StringUtils;
Ва ин аст, ҳамааш дар сумка аст))

1. Намунаҳо аз лоиҳаи воқеӣ

  • усули leftPad

Мисоли аввал умуман он қадар беақл ба назар мерасад, ки хеле хуб аст, ки ҳамкорони ман дар бораи StringUtils.leftPad медонистанд ва ба ман гуфтанд. Вазифа аз чӣ иборат буд: code тавре сохта шуда буд, ки агар маълумот дуруст наояд, тағир додан лозим буд. Интизор мерафт, ки майдони сатр бояд танҳо аз рақамҳо иборат бошад, яъне. агар дарозии он 3 бошад ва арзиши он 1 бошад, пас вуруд бояд "001" бошад. Ин аст, ки аввал шумо бояд ҳамаи ҷойҳоро тоза кунед ва сипас онро бо сифрҳо пӯшонед. Барои равшан шудани моҳияти вазифа мисолҳои бештар: аз “12“ -> “012” аз “1“ -> “001” Ва ғайра. Ман чӣ кор кардам? Инро дар синфи LeftPadExample тасвир кардааст . Ман як усуле навиштам, ки ҳамаи инро иҷро мекунад:
public static String ownLeftPad(String value) {
   String trimmedValue = value.trim();

   if(trimmedValue.length() == value.length()) {
       return value;
   }

   StringBuilder newValue = new StringBuilder(trimmedValue);

   IntStream.rangeClosed(1, value.length() - trimmedValue.length())
           .forEach(it -> newValue.insert(0, "0"));
   return newValue.toString();
}
Ман ҳамчун асос фикр кардам, ки мо метавонем фарқияти байни арзиши аслӣ ва буридашударо ба даст орем ва онро бо сифрҳо дар пеш пур кунем. Барои ин ман IntStream-ро n маротиба истифода бурдам. Ва ин бешубҳа бояд санҷида шавад. Ин аст он чизе ки ман метавонистам кор кунам, агар ман дар бораи усули StringUtils.leftPad пешакӣ медонистам :
public static String apacheCommonLeftPad(String value) {
   return StringUtils.leftPad(value.trim(), value.length(), "0");
}
Тавре ки шумо мебинед, code хеле камтар аст ва китобхонаи аз ҷониби ҳама тасдиқшуда низ истифода мешавад. Бо ин мақсад, ман дар синфи LeftPadExampleTest ду санҷиш эҷод кардам (одатан вақте ки онҳо нақшаи санҷиши синфро доранд, онҳо синферо бо ҳамон ном эҷод мекунанд + Test дар як баста, танҳо дар src/test/java). Ин санҷишҳо як усулро месанҷанд, то боварӣ ҳосил кунанд, ки он арзишро дуруст тағир медиҳад, пас дигар. Албатта, санҷишҳои зиёде бояд навишта шаванд, аммо санҷиш дар ҳолати мо мавзӯи асосӣ нест:
package com.github.javarushcommunity.stringutilsdemo;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

@DisplayName("Unit-level testing for LeftPadExample")
class LeftPadExampleTest {

   @DisplayName("Should transform by using ownLeftPad method as expected")
   @Test
   public void shouldTransformOwnLeftPadAsExpected() {
       //given
       String value = "1   ";
       String expectedTransformedValue = "0001";

       //when
       String transformedValue = LeftPadExample.ownLeftPad(value);

       //then
       Assertions.assertEquals(expectedTransformedValue, transformedValue);
   }

   @DisplayName("Should transform by using StringUtils method as expected")
   @Test
   public void shouldTransformStringUtilsLeftPadAsExpected() {
       //given
       String value = "1   ";
       String expectedTransformedValue = "0001";

       //when
       String transformedValue = LeftPadExample.apacheCommonLeftPad(value);

       //then
       Assertions.assertEquals(expectedTransformedValue, transformedValue);
   }

}
Ҳоло ман метавонам дар бораи санҷишҳо чанд шарҳ диҳам. Онҳо бо истифода аз JUnit 5 навишта шудаанд:
  1. Санҷиш ҳамчун санҷиш баррасӣ карда мешавад, агар он дорои эзоҳоти мувофиқ бошад - @Test.
  2. Агар тавсифи кори тест бо ном душвор бошад ё тавсиф дароз ва барои хондан нороҳат бошад, шумо метавонед тавзеҳи @DisplayName-ро илова кунед ва онро тавсифи муқаррарӣ созед, ки ҳангоми гузаронидани санҷишҳо намоён хоҳад шуд.
  3. Ҳангоми навиштани тестҳо ман равиши BDD-ро истифода мебарам, ки дар он санҷишҳоро ба қисмҳои мантиқӣ тақсим мекунам:
    1. // дода шудааст - блоки насби маълумот пеш аз санҷиш;
    2. //блок кай оғоз мешавад, ки қисми рамзе, ки мо озмоиш мекунем;
    3. //пас блокест, ки дар он натиҷаҳои блоки when тафтиш карда мешаванд.
Агар шумо онҳоро идора кунед, онҳо тасдиқ мекунанд, ки ҳама чиз тавре ки интизор буд, кор мекунад.

  • усули stripStart

Дар ин ҷо ба ман лозим буд, ки масъаларо бо сатре ҳал кунам, ки дар аввал фосила ва вергул дошта бошад. Баъди дигаргунсозй онхо бояд мазмуни нав надоштанд. Изҳороти мушкилот аз ҳарвақта равшантар аст. Якчанд мисолҳо фаҳмиши моро мустаҳкам мекунанд: “, , books” -> “books” “,,, books” -> “books” b , books” -> “b , books” Тавре ки дар мавриди leftPad, ман илова кардам Синфи StrimStartExample , ки дар он ду усул дорад. Як - бо ҳалли худ:
public static String ownStripStart(String value) {
   int index = 0;
   List commaSpace = asList(" ", ",");
   for (int i = 0; i < value.length(); i++) {
       if (commaSpace.contains(String.valueOf(value.charAt(i)))) {
           index++;
       } else {
           break;
       }
   }
   return value.substring(index);
}
Дар ин ҷо идея пайдо кардани шохис буд, ки аз он дигар фосила ё вергул мавҷуд нест. Агар онҳо дар аввал дар он ҷо набошанд, пас индекс сифр мешавад. Ва дуюм - бо ҳалли тавассути StringUtils :
public static String apacheCommonLeftPad(String value) {
   return StringUtils.stripStart(value, StringUtils.SPACE + COMMA);
}
Дар ин ҷо мо маълумоти аргументи аввалро дар бораи он, ки мо бо кадом сатр кор карда истодаем, мегузарем ва дар дуюм сатри иборат аз аломатҳоеро мегузарем, ки бояд гузаронид. Мо синфи StripStartExampleTestро ҳамин тавр эҷод мекунем :
package com.github.javarushcommunity.stringutilsdemo;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

@DisplayName("Unit-level testing for StripStartExample")
class StripStartExampleTest {

   @DisplayName("Should transform by using stripStart method as expected")
   @Test
   public void shouldTransformOwnStripStartAsExpected() {
       //given
       String value = ", , books";
       String expectedTransformedValue = "books";

       //when
       String transformedValue = StripStartExample.ownStripStart(value);

       //then
       Assertions.assertEquals(expectedTransformedValue, transformedValue);
   }

   @DisplayName("Should transform by using StringUtils method as expected")
   @Test
   public void shouldTransformStringUtilsStripStartAsExpected() {
       //given
       String value = ", , books";
       String expectedTransformedValue = "books";

       //when
       String transformedValue = StripStartExample.apacheCommonLeftPad(value);

       //then
       Assertions.assertEquals(expectedTransformedValue, transformedValue);
   }
}

  • усули холӣ

Ин усул, албатта, хеле соддатар аст, аммо ин онро фоиданоктар намекунад. Он имкониятҳои усули String.isEmpty() -ро васеъ мекунад , ки он инчунин чекро барои нул илова мекунад. Барои чӣ? Барои пешгирӣ кардани NullPointerException, яъне пешгирӣ кардани даъват кардани усулҳо дар тағирёбанда, ки null аст . Аз ин рӯ, барои нанавиштан:
if(value != null && value.isEmpty()) {
   //doing something
}
Шумо метавонед инро танҳо иҷро кунед:
if(StringUtils.isEmpty(value)) {
   //doing something
}
Бартарии ин усул дар он аст, ки дар кучо кадом усул истифода мешавад, фавран маълум мешавад.

2. Таҳлor усулҳои дигари синфи StringUtils

Акнун биёед дар бораи он усулҳое сӯҳбат кунем, ки ба назари ман, низ сазовори таваҷҷӯҳ аст. Агар умуман дар бораи StringUtils сухан ронем , бояд гуфт, ки он усулҳои бехатари безарарро ба монанди усулҳои дар синфи String мавҷудбуда таъмин мекунад (чунон ки дар усули isEmpty аст ). Биёед онҳоро аз сар гузаронем:

  • усули муқоиса

Чунин усул дар String вуҷуд дорад ва NullPointerException-ро мепартояд, агар ҳангоми муқоисаи ду сатр яке аз онҳо сифр бошад. Барои пешгирӣ кардани санҷишҳои зишти codeи мо, мо метавонем усули StringUtils.compare(String str1, String str2) -ро истифода барем : он int-ро дар натиҷаи муқоиса бармегардонад. Ин арзишҳо чӣ маъно доранд? int = 0 агар онҳо якхела бошанд (ё ҳарду сифр бошанд). int < 0, агар str1 аз str2 камтар бошад. int > 0, агар str1 аз str2 бузургтар бошад. Инчунин, агар шумо ба ҳуҷҷатҳои онҳо назар кунед, Javadoc-и ин усул сенарияҳои зеринро пешниҳод мекунад:
StringUtils.compare(null, null)   = 0
StringUtils.compare(null , "a")   < 0
StringUtils.compare("a", null)    > 0
StringUtils.compare("abc", "abc") = 0
StringUtils.compare("a", "b")     < 0
StringUtils.compare("b", "a")     > 0
StringUtils.compare("a", "B")     > 0
StringUtils.compare("ab", "abc")  < 0

  • усулҳои... дар бар мегирад

Дар ин ҷо таҳиягарони коммуналӣ як таркиш доштанд. Ҳар усуле, ки шумо мехоҳед, он ҷост. Ман қарор додам, ки онҳоро якҷоя кунам:
  1. дорои усулест, ки тафтиш мекунад, ки сатри интизоршуда дар дохor сатри дигар аст. Ин чӣ гуна муфид аст? Шумо метавонед ин усулро истифода баред, агар шумо бояд боварӣ ҳосил кунед, ки дар матн калимаи муайян мавҷуд аст.

    Мисолҳо:

    StringUtils.contains(null, *)     = false
    StringUtils.contains(*, null)     = false
    StringUtils.contains("", "")      = true
    StringUtils.contains("abc", "")   = true
    StringUtils.contains("abc", "a")  = true
    StringUtils.contains("abc", "z")  = false

    Боз, амнияти NPE (Null Pointer Exception) мавҷуд аст.

  2. containAny усулест, ки мавҷудияти ягон аломати дар сатр мавҷудбударо тафтиш мекунад. Инчунин як чизи муфид: шумо аксар вақт ин корро кардан лозим аст.

    Намунаҳо аз ҳуҷҷатҳо:

    StringUtils.containsAny(null, *)                  = false
    StringUtils.containsAny("", *)                    = false
    StringUtils.containsAny(*, null)                  = false
    StringUtils.containsAny(*, [])                    = false
    StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true
    StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true
    StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true
    StringUtils.containsAny("aba", ['z'])             = false

  3. containIgnoreCase як тамдиди муфид барои усули contain аст . Дар ҳақиқат, барои тафтиши чунин ҳолат бе ин усул, шумо бояд аз якчанд вариант гузаред. Ва аз ин рӯ, танҳо як усул ба таври мувофиқ истифода мешавад.

  4. Якчанд мисол аз ҳуҷҷатҳо:

    StringUtils.containsIgnoreCase(null, *) = false
    StringUtils.containsIgnoreCase(*, null) = false
    StringUtils.containsIgnoreCase("", "") = true
    StringUtils.containsIgnoreCase("abc", "") = true
    StringUtils.containsIgnoreCase("abc", "a") = true
    StringUtils.containsIgnoreCase("abc", "z") = false
    StringUtils.containsIgnoreCase("abc", "A") = true
    StringUtils.containsIgnoreCase("abc", "Z") = false

  5. containNone - аз рӯи ном, шумо аллакай фаҳмида метавонед, ки чӣ тафтиш карда мешавад. Дар дохor он набояд хатҳо бошад. Як чизи муфид, бешубҳа. Ҷустуҷӯи зуд барои баъзе аломатҳои номатлуб;). Дар боти телеграммаи худ мо фаҳшро филтр мекунем ва ин усулҳои хандаоварро сарфи назар намекунем.

    Ва мисолҳо, ки мо бе онҳо куҷо мешудем:

    StringUtils.containsNone(null, *)       = true
    StringUtils.containsNone(*, null)       = true
    StringUtils.containsNone("", *)         = true
    StringUtils.containsNone("ab", '')      = true
    StringUtils.containsNone("abab", 'xyz') = true
    StringUtils.containsNone("ab1", 'xyz')  = true
    StringUtils.containsNone("abz", 'xyz')  = false

  • усули defaultString

Як қатор усулҳое, ки барои пешгирӣ кардани илова кардани маълумоти иловагӣ кӯмак мекунанд, агар сатр сифр бошад ва шумо бояд арзиши пешфарзро муқаррар кунед. Вариантҳои зиёде мавҷуданд, ки ба ҳар завқ мувофиқанд. Дар байни онҳо StringUtils.defaultString (ниҳоии String, defaultStr сатри ниҳоӣ) мебошад - агар str нул бошад, мо танҳо арзишро ба defaultStr мегузаронем . Намунаҳо аз ҳуҷҷатҳо:
StringUtils.defaultString(null, "NULL")  = "NULL"
StringUtils.defaultString("", "NULL")    = ""
StringUtils.defaultString("bat", "NULL") = "bat"
Истифодаи он хеле қулай аст, вақте ки шумо синфи POJO бо маълумот эҷод мекунед.

  • Усули deleteWhitespace

Ин усули ҷолиб аст, гарчанде ки барои татбиқи он имконоти зиёде вуҷуд надорад. Дар баробари ин, агар чунин ҳолат ба миён ояд, усул бешубҳа хеле муфид хоҳад буд. Он ҳама фосилаҳоро аз сатр хориҷ мекунад. Ҳар ҷое, ки ин холигоҳ бошад, аз он осоре нахоҳад монд))) Намунаҳо аз ҳуҷҷатҳо:
StringUtils.deleteWhitespace(null)         = null
StringUtils.deleteWhitespace("")           = ""
StringUtils.deleteWhitespace("abc")        = "abc"
StringUtils.deleteWhitespace("   ab  c  ") = "abc"

  • endsWith усули

Барои худ гап мезанад. Ин усули хеле муфид аст: он тафтиш мекунад, ки сатр бо сатри пешниҳодшуда тамом мешавад ё не. Ин аксар вақт зарур аст. Албатта, шумо метавонед чекро худатон нависед, аммо истифодаи усули тайёр равшантар қулайтар ва беҳтар аст. Мисолҳо:
StringUtils.endsWith(null, null)      = true
StringUtils.endsWith(null, "def")     = false
StringUtils.endsWith("abcdef", null)  = false
StringUtils.endsWith("abcdef", "def") = true
StringUtils.endsWith("ABCDEF", "def") = false
StringUtils.endsWith("ABCDEF", "cde") = false
StringUtils.endsWith("ABCDEF", "")    = true
Тавре ки шумо мебинед, ҳама чиз бо як сатри холӣ хотима меёбад))) Ман фикр мекунам, ки ин мисол (StringUtils.endsWith("ABCDEF", "") = true) танҳо бонус аст, зеро ин бемаънӣ аст) Усул низ ҳаст, ки парвандаро сарфи назар мекунад.

  • усули баробар

Намунаи олии усули безарар, ки ду сатрро муқоиса мекунад. Ҳар чизе ки мо дар он ҷо гузорем, ҷавоб дар он ҷо хоҳад буд ва он бе хато хоҳад буд. Мисолҳо:
StringUtils.equals(null, null)   = true
StringUtils.equals(null, "abc")  = false
StringUtils.equals("abc", null)  = false
StringUtils.equals("abc", "abc") = true
StringUtils.equals("abc", "ABC") = false
Албатта, equalsIgnoreCase низ вуҷуд дорад - ҳама чиз маҳз ҳамин тавр анҷом дода мешавад, танҳо мо парвандаро сарфи назар мекунем. Биёед мебинем?
StringUtils.equalsIgnoreCase(null, null)   = true
StringUtils.equalsIgnoreCase(null, "abc")  = false
StringUtils.equalsIgnoreCase("abc", null)  = false
StringUtils.equalsIgnoreCase("abc", "abc") = true
StringUtils.equalsIgnoreCase("abc", "ABC") = true

  • баробар ҳама гуна усул

Биёед пеш равем ва усули баробарро васеъ кунем . Биёед бигӯем, ки ба ҷои якчанд санҷиши баробарӣ, мо мехоҳем як тафтиш кунем. Барои ин мо метавонем сатреро гузаронем, ки бо он маҷмӯи сатрҳо муқоиса карда мешаванд; агар яке аз онҳо ба сатрҳои пешниҳодшуда баробар бошад, он TRUE хоҳад буд. Мо як сатр ва маҷмӯи сатрҳоро мегузарем, то онҳоро бо ҳамдигар муқоиса кунем (сатри аввал бо сатрҳои коллексия). Мушкил? Инҳоянд мисолҳо аз ҳуҷҷатҳо, ки ба шумо барои фаҳмидани он ки чӣ маъно доранд:
StringUtils.equalsAny(null, (CharSequence[]) null) = false
StringUtils.equalsAny(null, null, null)    = true
StringUtils.equalsAny(null, "abc", "def")  = false
StringUtils.equalsAny("abc", null, "def")  = false
StringUtils.equalsAny("abc", "abc", "def") = true
StringUtils.equalsAny("abc", "ABC", "DEF") = false
Инчунин equalsAnyIgnoreCase мавҷуд аст . Ва мисолҳо барои он:
StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
StringUtils.equalsAnyIgnoreCase(null, null, null)    = true
StringUtils.equalsAnyIgnoreCase(null, "abc", "def")  = false
StringUtils.equalsAnyIgnoreCase("abc", null, "def")  = false
StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true

Хатти поён

Дар натиҷа, мо бо он меравем, ки StringUtils чист ва он чӣ гуна усулҳои муфид дорад. Хуб, бо дарки он, ки чунин чизҳои муфид вуҷуд доранд ва дар ҷойҳое, ки бо ҳалли тайёр масъаларо пӯшидан мумкин аст, ҳар дафъа бо асобағол девор кардан лозим нест. Умуман, мо танҳо як қисми усулҳоро таҳлил кардем. Агар шумо хоҳед, ман метавонам идома диҳам: онҳо зиёданд ва онҳо дар ҳақиқат сазовори таваҷҷӯҳ мебошанд. Агар шумо ягон ғояе дошта бошед, ки чӣ гуна онро пешниҳод кардан мумкин аст, лутфан нависед - ман ҳамеша барои ғояҳои нав кушода ҳастам. Ҳуҷҷатҳои усулҳо хеле хуб навишта шудаанд, мисолҳои санҷишӣ бо натиҷаҳо илова карда шудаанд, ки барои беҳтар фаҳмидани кори усул кӯмак мекунанд. Аз ин рӯ, мо аз хондани ҳуҷҷатҳо худдорӣ намекунем: он шубҳаҳои шуморо дар бораи фаъолияти утorта бартараф мекунад. Барои ба даст овардани таҷрибаи нави рамзгузорӣ, ман ба шумо маслиҳат медиҳам, ки бубинед, ки синфҳои коммуналӣ чӣ гуна сохта мешаванд ва навишта мешаванд. Ин дар оянда муфид хоҳад буд, зеро одатан ҳар як лоиҳа дарсҳои худро дорад ва таҷрибаи навиштани онҳо муфид хоҳад буд. Ба таври анъанавӣ, ман тавсия медиҳам, ки ба ҳисоби ман дар Github обуна шавед ) Барои онҳое, ки дар бораи лоиҳаи ман бо боти телеграмма намедонанд, дар ин ҷо пайванд ба мақолаи аввал аст . Ташаккур ба ҳама барои хондан. Ман якчанд истинодҳои муфидро дар зер илова кардам.
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION