apeescape2.com
  • Põhiline
  • Finantsprotsessid
  • Mobiilne
  • Kasumlikkus Ja Tõhusus
  • Töö Tulevik
Tagumine Ots

10 kõige levinumat kevadraamistiku viga

Kevad on vaieldamatult üks populaarsemaid Java-raamistikke ja ka taltsutatav vägev metsaline. Ehkki selle põhimõisteid on üsna lihtne mõista, nõuab tugevaks kevade arendajaks saamine aega ja vaeva.

Selles artiklis käsitleme kevadel levinumaid vigu, mis on spetsiaalselt suunatud veebirakendustele ja Spring Bootile. As Spring Boot'i veebisait osutab, võtab Spring Boot arvamusega seisukoht selle kohta, kuidas tootmiskõlbulikke rakendusi tuleks üles ehitada, nii et selles artiklis püütakse seda vaadet jäljendada ja anda ülevaade mõnest näpunäidetest, mis on hästi kaasatud Spring Boot'i tavalisse veebirakenduste arendusse.



Kui te pole Spring Bootiga eriti kursis, kuid soovite siiski mõnda mainitud asja proovida, olen ma loonud sellele artiklile lisatud GitHubi hoidla . Kui tunnete end artikli ajal mingil hetkel kaotsi, soovitan kloonida hoidla ja mängida kohalikus masinas oleva koodiga.



Üldine viga nr 1: liiga madalale minek

Lõpetame selle levinud veaga, sest ' pole siin leiutatud ”Sündroom on tarkvaraarenduse maailmas üsna tavaline. Tundub, et selle all kannatavad sümptomid, sealhulgas tavaliselt kasutatava koodi regulaarselt ümber kirjutamine ja paljud arendajad.

Ehkki konkreetse raamatukogu sisemuse ja selle rakendamise mõistmine on enamasti hea ja vajalik (ja see võib olla ka suurepärane õppeprotsess), on teie kui tarkvarainseneri arengule kahjulik pidevalt tegeleda sama madalama taseme rakendusega üksikasjad. On olemas põhjus, miks eksisteerivad sellised abstraktsioonid ja raamistikud nagu Spring, mis on just selleks, et eraldada teid korduvast käsitsi töötamisest ja võimaldada teil keskenduda kõrgema taseme detailidele - oma domeeni objektidele ja äriloogikale.



Nii et võtke omaks abstraktsioonid - järgmine kord, kui olete mõne konkreetse probleemiga silmitsi, tehke kõigepealt kiire otsing ja tehke kindlaks, kas seda probleemi lahendav raamatukogu on juba Springisse integreeritud; tänapäeval on tõenäoline, et leiate sobiva olemasoleva lahenduse. Kasuliku raamatukogu näitena kasutan Projekt Lombok selle artikli ülejäänud näidetes toodud märkused. Lombokit kasutatakse katlakoodigeneraatorina ja loodetaval arendajal ei tohiks loodetavasti olla probleeme raamatukoguga tutvumisel. Näiteks vaadake, mida tavaline Java bean ”Näeb välja nagu Lomboki puhul:

@Getter @Setter @NoArgsConstructor public class Bean implements Serializable { int firstBeanProperty; String secondBeanProperty; }

Nagu võite ette kujutada, koostatakse ülaltoodud kood:

public class Bean implements Serializable { private int firstBeanProperty; private String secondBeanProperty; public int getFirstBeanProperty() { return this.firstBeanProperty; } public String getSecondBeanProperty() { return this.secondBeanProperty; } public void setFirstBeanProperty(int firstBeanProperty) { this.firstBeanProperty = firstBeanProperty; } public void setSecondBeanProperty(String secondBeanProperty) { this.secondBeanProperty = secondBeanProperty; } public Bean() { } }

Pange siiski tähele, et peate tõenäoliselt installima pistikprogrammi juhuks, kui kavatsete oma IDE-ga kasutada Lombokit. IntelliJ IDEA pistikprogrammi versioon on leitav siin .



kuidas lisada Wordpressile api

Üldine viga nr 2: ‘Lekkivad’ sisemised

Oma sisemise struktuuri paljastamine pole kunagi hea mõte, sest see loob teenuse kujundamisel paindumatuse ja soodustab seetõttu halbu kodeerimistavasid. Lekkivad sisemised osad ilmnevad andmebaasistruktuuri teatud API-punktidest juurdepääsetavaks muutmise kaudu. Oletame näiteks, et järgmine POJO („Plain Old Java Object”) tähistab teie andmebaasi tabelit:

@Entity @NoArgsConstructor @Getter public class TopTalentEntity { @Id @GeneratedValue private Integer id; @Column private String name; public TopTalentEntity(String name) { this.name = name; } }

Oletame, et on olemas lõpp-punkt, mis peab juurde pääsema TopTalentEntity andmed. Nii ahvatlev kui tagasipöördumine võib olla TopTalentEntity juhtudel oleks paindlikum lahendus uue klassi loomine, et tähistada TopTalentEntity andmed API lõpp-punkti kohta:

@AllArgsConstructor @NoArgsConstructor @Getter public class TopTalentData { private String name; }

Nii ei nõua andmebaasi back-endis muudatuste tegemine teeninduskihis täiendavaid muudatusi. Mõelge, mis juhtuks juhul, kui TopTalentEntity väljale parool lisatakse kasutajate parooliräsi andmebaasi salvestamiseks - ilma pistikuta nagu TopTalentData, paljastaksite teenuse esiotsa muutmise unustades kogemata väga ebasoovitava salajase teabe!

Üldine viga nr 3: murede lahusoleku puudumine

Kui teie rakendus kasvab, hakkab koodide korraldamine muutuma üha olulisemaks küsimuseks. Irooniline, et enamus headest tarkvaratehnika põhimõtetest hakkavad mastaapselt lagunema - eriti juhtudel, kui rakenduse arhitektuuri kujundamisele pole palju mõeldud. Üks levinumaid vigu, mida arendajad kipuvad järele andma, on koodiprobleemide segamine ja seda on äärmiselt lihtne teha!

Mis tavaliselt puruneb murede lahusus on lihtsalt uue funktsionaalsuse „viskamine” olemasolevatesse klassidesse. See on loomulikult suurepärane lühiajaline lahendus (alustajate jaoks nõuab see vähem tippimist), kuid paratamatult muutub see probleemiks teel edasi, olgu see siis testimise, hoolduse või kuskil vahepeal. Mõelge järgmisele kontrollerile, mis tagastab TopTalentData oma hoidlast:

@RestController public class TopTalentController { private final TopTalentRepository topTalentRepository; @RequestMapping('/toptal/get') public List getTopTalent() { return topTalentRepository.findAll() .stream() .map(this::entityToData) .collect(Collectors.toList()); } private TopTalentData entityToData(TopTalentEntity topTalentEntity) { return new TopTalentData(topTalentEntity.getName()); } }

Esialgu ei pruugi tunduda, et sellel koodilõigul on midagi eriti valesti; see pakub TopTalentData loendi mida otsitakse TopTalentEntity -st juhtumeid. Lähemalt vaadates näeme aga, et tegelikult on mõned asjad, mis TopTalentController esineb siin; nimelt on see konkreetse lõpp-punkti taotluste kaardistamine, hoidlast andmete hankimine ja TopTalentRepository -lt saadud üksuste teisendamine teises vormingus. Puhtam lahendus oleks nende probleemide lahutamine oma klassidesse. See võib välja näha umbes selline:

@RestController @RequestMapping('/toptal') @AllArgsConstructor public class TopTalentController { private final TopTalentService topTalentService; @RequestMapping('/get') public List getTopTalent() { return topTalentService.getTopTalent(); } } @AllArgsConstructor @Service public class TopTalentService { private final TopTalentRepository topTalentRepository; private final TopTalentEntityConverter topTalentEntityConverter; public List getTopTalent() { return topTalentRepository.findAll() .stream() .map(topTalentEntityConverter::toResponse) .collect(Collectors.toList()); } } @Component public class TopTalentEntityConverter { public TopTalentData toResponse(TopTalentEntity topTalentEntity) { return new TopTalentData(topTalentEntity.getName()); } }

Selle hierarhia täiendav eelis on see, et see võimaldab meil klassi nime kontrollides kindlaks teha funktsionaalsuse asukoha. Pealegi võime testimise käigus vajaduse korral mõne klassi hõlpsasti asendada mõnitava rakendusega.

Üldine viga nr 4: ebajärjekindlus ja halb vigade käsitlemine

Järjepidevuse teema ei pruugi tingimata olla ainuüksi Springile (või Java-le), kuid on siiski oluline aspekt, mida tuleb kevade projektide kallal töötamisel arvesse võtta. Kuigi kodeerimisstiil võib olla vaieldav (ja see on tavaliselt meeskonnas või kogu ettevõttes kokkuleppe küsimus), osutub ühise standardi omamine suureks tootlikkuse abivahendiks. See kehtib eriti mitme inimese meeskondade kohta; järjepidevus võimaldab kätteandmist ilma, et palju ressursse kulutataks käes hoidmisele või esitataks pikki selgitusi erinevate klasside kohustuste kohta

Mõelge kevadisele projektile koos selle erinevate konfiguratsioonifailide, teenuste ja kontrolleritega. Nende nimetamisel semantiliselt järjepidev olemine loob hõlpsasti otsitava struktuuri, kus iga uus arendaja saab koodi ümber käia; konfigureerimisliidete lisamine teie konfiguratsiooniklassidele, teenuse järelliited teie teenustele ja kontrolleri sufiksid teie kontrolleritele.

Järjepidevuse teemaga tihedalt seotud vääritega töötlemine serveripoolel väärib erilist rõhutamist. Kui pidite kunagi käsitsema halvasti kirjutatud API erandivastusi, siis ilmselt teate, miks - erandite õigesti sõelumine võib olla piin ja veelgi valusam põhjuse väljaselgitamine, miks need erandid üldse tekkisid.

API-arendajana soovite ideaalis katta kõik kasutajale suunatud otspunktid ja tõlkida need tavalisse veavormingusse. See tähendab tavaliselt üldise veakoodi ja kirjelduse olemasolu, mitte kopeerimislahendust a) teate „500 sisemise serveri viga” tagastamiseks või b) korstnajälje lihtsalt kasutajale viskamiseks (mida peaks tegelikult iga hinna eest vältima) kuna see paljastab teie sisemisi osi lisaks sellele, et seda on keeruline kliendipoolselt käsitseda).

Tavalise tõrketeate vormingu näide võib olla:

@Value public class ErrorResponse { private Integer errorCode; private String errorMessage; }

Midagi sarnast on tavaliselt kõige populaarsemates API-des ja see töötab hästi, kuna seda saab hõlpsalt ja süstemaatiliselt dokumenteerida. Erandite sellesse vormingusse tõlkimise saab anda @ExceptionHandler meetodi annotatsioon (annotatsiooni näide on levinud veast nr 6).

Üldine viga nr 5: mitmikeermeliste lugudega valesti tegelemine

Sõltumata sellest, kas seda leidub töölaua- või veebirakendustes, kevad või mitte kevad, võib multilõngamine olla kõva pähkel. Programmide paralleelse käivitamise põhjustatud probleemid on närvesöövalt raskesti tabatavad ja neid on sageli äärmiselt raske siluda - tegelikult tuleneb probleemi olemusest, kui mõistate, et tegelete paralleelse käivitamise probleemiga peate siluri täielikult loobuma ja kontrollima oma koodi käsitsi, kuni leiate algvea põhjuse. Kahjuks ei eksisteeri selliste küsimuste lahendamiseks küpsiste lõikuri lahendust; sõltuvalt konkreetsest juhtumist peate olukorda hindama ja seejärel ründama probleemi nurga alt, mida peate kõige paremaks.

Ideaalis sooviksite muidugi mitmikeermelisi vigu täielikult vältida. Jällegi ei ole selleks kõigile ühesugust lähenemisviisi, kuid siin on mõned praktilised kaalutlused silumiseks ja mitmikeermeliste vigade ennetamiseks:

Vältige ülemaailmset riiki

Esiteks pidage alati meeles 'globaalse riigi' küsimust. Kui loote mitmetoimelist rakendust, tuleks hoolikalt jälgida ja võimalusel täielikult eemaldada kõike, mis on globaalselt muudetav. Kui on põhjust, miks globaalne muutuja peab muutma jääma, kasutage seda hoolikalt sünkroniseerimine ja jälgige oma rakenduse toimivust, et veenduda, et see pole hiljuti kehtestatud ooteperioodide tõttu aeglane.

Vältige muutlikkust

See pärineb otse funktsionaalne programmeerimine ning OOP-ga kohandatud väidab, et tuleks vältida klassi muutlikkust ja oleku muutmist. Lühidalt tähendab see setter-meetoditest loobumist ja privaatsete lõplike väljade olemasolu kõigis oma mudeli klassides. Ainus kord, kui nende väärtused muteeruvad, on ehituse ajal. Nii võite olla kindel, et vaidlusprobleeme ei teki ja objekti omadustele juurdepääs annab alati õiged väärtused.

Oluliste andmete logimine

Hinnake, kus teie rakendus võib probleeme tekitada, ja logige kõik olulised andmed ennetavalt sisse. Vea ilmnemisel olete tänulik, et teil on teavet selle kohta, millised taotlused on saadud, ja saate parema ülevaate selle kohta, miks teie rakendus ebaõigesti käitus. Jällegi on vaja arvestada, et logimine toob sisse täiendava faili I / O ja seetõttu ei tohiks seda kuritarvitada, kuna see võib teie rakenduse toimimist tõsiselt mõjutada.

Olemasolevate rakenduste taaskasutamine

Alati, kui vajate oma lõimete kudemist (nt erinevatele teenustele asünkroonitaotluste esitamiseks), kasutage oma lahenduste loomise asemel uuesti olemasolevaid turvalisi rakendusi. See tähendab enamasti kasutamist ExecutorServices ja Java 8 korralik funktsionaalne stiil CompletableFutures lõime loomiseks. Spring võimaldab ka asünkroonset päringute töötlemist Edasilükatud tulemus klass.

ostujõu porteri viis jõudu

Üldine viga nr 6: märkuste põhjal valideerimata jätmine

Kujutame ette, et meie varasem TopTalenti teenus nõuab uute tipp-talentide lisamiseks lõpp-punkti. Oletagem, et mingil tõeliselt mõjuval põhjusel peab iga uus nimi olema täpselt 10 tähemärki pikk. Üks viis selle tegemiseks võib olla järgmine:

@RequestMapping('/put') public void addTopTalent(@RequestBody TopTalentData topTalentData) { boolean nameNonExistentOrHasInvalidLength = Optional.ofNullable(topTalentData) .map(TopTalentData::getName) .map(name -> name.length() == 10) .orElse(true); if (nameNonExistentOrInvalidLength) { // throw some exception } topTalentService.addTopTalent(topTalentData); }

Kuid ülaltoodu (lisaks halvasti ülesehitatud) ei ole tegelikult „puhas” lahendus. Kontrollime rohkem kui ühte tüüpi kehtivust (nimelt, et TopTalentData ei ole null, ja see TopTalentData.name pole null, ja see TopTalentData.name on 10 tähemärki), samuti erandi tegemine, kui andmed on valed.

Seda saab rakendades palju puhtamalt teostada Talveunerežiimi valideerija kevadega. Refrakteerime kõigepealt addTopTalent meetod valideerimise toetamiseks:

@RequestMapping('/put') public void addTopTalent(@Valid @NotNull @RequestBody TopTalentData topTalentData) { topTalentService.addTopTalent(topTalentData); } @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleInvalidTopTalentDataException(MethodArgumentNotValidException methodArgumentNotValidException) { // handle validation exception }

Lisaks peame TopTalentData -is märkima, millist omadust soovime kinnitada klass:

public class TopTalentData { @Length(min = 10, max = 10) @NotNull private String name; }

Nüüd võtab Spring taotluse kinni ja kinnitab selle enne meetodi kasutamist - pole vaja kasutada täiendavaid käsitsi teste.

Teine viis, kuidas oleksime sama saavutanud, on oma märkuste loomine. Kuigi tavaliselt kasutate kohandatud märkusi ainult siis, kui teie vajadused ületavad Hibernate sisseehitatud piirangute komplekt , selle näite jaoks teeskleme, et @ Pikkust pole olemas. Teeksite valideerija, mis kontrollib stringi pikkust, luues kaks täiendavat klassi, ühe valideerimiseks ja teise omaduste märkimiseks:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = { MyAnnotationValidator.class }) public @interface MyAnnotation { String message() default 'String length does not match expected'; Class[] groups() default {}; Class[] payload() default {}; int value(); } @Component public class MyAnnotationValidator implements ConstraintValidator { private int expectedLength; @Override public void initialize(MyAnnotation myAnnotation) { this.expectedLength = myAnnotation.value(); } @Override public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) }

Pange tähele, et nendel juhtudel nõuavad probleemide lahutamise parimad tavad kinnisvara kehtivaks märkimist, kui see on null (s == null meetodi isValid sees) ja seejärel kasutage @NotNull märkus, kui see on kinnistu lisanõue:

public class TopTalentData { @MyAnnotation(value = 10) @NotNull private String name; }

Levinud viga nr 7: (endiselt) XML-põhise konfiguratsiooni kasutamine

Kui Spring oli eelmiste Springsi versioonide jaoks hädavajalik, siis tänapäeval saab suurema osa seadistustest teha ainult Java-koodi / märkuste abil; XML-konfiguratsioonid kujutavad endast lihtsalt täiendavat ja mittevajalikku katlakoodi koodi.

See artikkel (ja ka sellega kaasnev GitHubi hoidla) kasutab märkeid kevade ja kevade konfigureerimiseks. Teab, milliseid ube see peaks ühendama, kuna juurpakett on märgitud tähisega @SpringBootApplication liitmärkus, näiteks:

@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

Liitmärkus (selle kohta saate lisateavet Kevadine dokumentatsioon annab Springile lihtsalt vihje, milliseid pakendeid tuleks ubade hankimiseks skannida. Meie konkreetsel juhul tähendab see, et juhtmete jaoks kasutatakse ülemise (co.kukurin) pakendi all järgmist:

  • @Component (TopTalentConverter, MyAnnotationValidator)
  • @RestController (TopTalentController)
  • @Repository (TopTalentRepository)
  • @Service (TopTalentService) klassid

Kui meil oleks veel täiendavaid @Configuration märkustega klassides kontrollitakse ka Java-põhist konfiguratsiooni.

Levinud viga nr 8: profiilide unustamine

Serveri arendamisel on sageli probleemiks erinevate konfiguratsioonitüüpide - tavaliselt teie tootmis- ja arenduskonfiguratsioonide - eristamine. Selle asemel, et asendada käsitsi erinevad konfiguratsioonikirjed iga kord, kui lähete üle testimiselt rakenduse juurutamisele, oleks tõhusam viis kasutada profiile.

Vaatleme juhtumit, kus kasutate kohaliku arenduse jaoks mälusisest andmebaasi, mille tootmisel on MySQL-i andmebaas. Sisuliselt tähendaks see, et kasutate mõlemale juurdepääsemiseks erinevat URL-i ja (loodetavasti) erinevaid volitusi. Vaatame, kuidas seda saaks teha kaks erinevat konfiguratsioonifaili:

application.yaml fail

# set default profile to 'dev' spring.profiles.active: dev # production database details spring.datasource.url: 'jdbc:mysql://localhost:3306/toptal' spring.datasource.username: root spring.datasource.password:

application-dev.yaml fail

spring.datasource.url: 'jdbc:h2:mem:' spring.datasource.platform: h2

Eeldatavasti ei taha te koodiga nokitsedes oma tootmisandmebaasis kogemata ühtegi toimingut sooritada, seega on mõttekas vaikeprofiil seada devile. Serveris saate seejärel konfiguratsiooniprofiili käsitsi alistada, andes -Dspring.profiles.active=prod parameeter JVM-ile. Teise võimalusena saate oma OS-i keskkonnamuutujale määrata ka soovitud vaikeprofiili.

Üldine viga nr 9: sõltuvuse süstimise omaks võtmata jätmine

Sõltuvussüstimise korralik kasutamine Springiga tähendab seda, et lubate tal kõik oma objektid kokku juhtida, skannides kõiki soovitud konfiguratsiooniklassid; see osutub kasulikuks suhete lahutamiseks ja muudab testimise palju lihtsamaks. Selle asemel, et tihedalt siduda klassid, tehes midagi sellist:

public class TopTalentController { private final TopTalentService topTalentService; public TopTalentController() { this.topTalentService = new TopTalentService(); } }

Lubame Springil juhtmestiku meie jaoks teha:

public class TopTalentController { private final TopTalentService topTalentService; public TopTalentController(TopTalentService topTalentService) { this.topTalentService = topTalentService; } }

Misko Hevery Google'i jutt selgitab põhjalikult sõltuvuse süstimise „miks”, nii et vaatame hoopis, kuidas seda praktikas kasutatakse. Murede lahutamist käsitlevas jaotises (levinud vead nr 3) lõime teenuse ja kontrolleri klassi. Oletame, et tahame kontrollerit testida eeldusel, et TopTalentService käitub õigesti. Teenuse tegeliku juurutamise asemele saab sisestada mõnitava objekti, pakkudes eraldi konfiguratsiooniklassi:

iooniline 1 kuni iooniline 2
@Configuration public class SampleUnitTestConfig { @Bean public TopTalentService topTalentService() { TopTalentService topTalentService = Mockito.mock(TopTalentService.class); Mockito.when(topTalentService.getTopTalent()).thenReturn( Stream.of('Mary', 'Joel').map(TopTalentData::new).collect(Collectors.toList())); return topTalentService; } }

Siis saame proovieseme süstida, käskides Springil kasutada SampleUnitTestConfig konfiguratsiooni tarnijana:

@ContextConfiguration(classes = { SampleUnitTestConfig.class })

See võimaldab meil kasutada kontekstikonfiguratsiooni, et sisestada kohandatud uba ühikutesti.

Levinud viga nr 10: testimise puudumine või vale testimine

Ehkki ühikutestimise idee on olnud meil juba pikka aega, näib, et paljud arendajad kas 'unustavad' seda teha (eriti kui see pole nii nõutud ) või lisage see lihtsalt tagantjärele. See pole ilmselgelt soovitav, sest testid peaksid mitte ainult kontrollima teie koodi õigsust, vaid olema ka dokumendid selle kohta, kuidas rakendus peaks erinevates olukordades käituma.

Veebiteenuste testimisel teete harva ainult puhtaid ühikuteste, kuna HTTP kaudu toimuv suhtlus nõuab tavaliselt Springsi DispatcherServlet ja vaadake, mis juhtub, kui tegelik HttpServletRequest on vastu võetud (muutes selle integratsioon testimine, valideerimine, jadastamine jne). PUHKUS kindel , Java DSL REST-teenuste hõlpsaks testimiseks, lisaks MockMVC-le, on osutunud väga elegantseks lahenduseks. Mõelge järgmisele sõltuvuse süstimisega koodijupile:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { Application.class, SampleUnitTestConfig.class }) public class RestAssuredTestDemonstration { @Autowired private TopTalentController topTalentController; @Test public void shouldGetMaryAndJoel() throws Exception { // given MockMvcRequestSpecification givenRestAssuredSpecification = RestAssuredMockMvc.given() .standaloneSetup(topTalentController); // when MockMvcResponse response = givenRestAssuredSpecification.when().get('/toptal/get'); // then response.then().statusCode(200); response.then().body('name', hasItems('Mary', 'Joel')); } }

SampleUnitTestConfig esitab TopTalentService mõnitava rakenduse sisse TopTalentController samal ajal kui kõik teised klassid on juhtmega ühendatud, kasutades rakendusklassi paketist juurdunud pakettide põhjal tuletatud standardset konfiguratsiooni. RestAssuredMockMvc kasutatakse lihtsalt kerge keskkonna seadistamiseks ja GET taotlus /toptal/get lõpp-punkt.

Kevadmeistriks saamine

Kevad on võimas raamistik, millega on lihtne alustada, kuid täieliku meisterlikkuse saavutamiseks on vaja pühendumist ja aega. Kui võtate aega raamistikuga tutvumiseks, parandab see teie pikas perspektiivis kindlasti teie tootlikkust ja aitab lõpuks kirjutada puhtama koodi ja saada paremaks arendajaks.

Kui otsite täiendavaid ressursse, Kevad tegevuses on hea praktiline raamat, mis hõlmab paljusid kevade põhiteemasid.

Super lihtne juhend ikonograafia kohta

Ui Disain

Super lihtne juhend ikonograafia kohta
ApeeScape teeb klientidega partnerlust, et uurida hüperkasvu andeid ja tehnoloogiastrateegiaid

ApeeScape teeb klientidega partnerlust, et uurida hüperkasvu andeid ja tehnoloogiastrateegiaid

Muu

Lemmik Postitused
Rubiini algoritmi dokumentatsioon koos AsciiDoci ja Knitriga
Rubiini algoritmi dokumentatsioon koos AsciiDoci ja Knitriga
Ärge laske end lollitada: arvutage töötajate ja konsultantide tegelikud kulud
Ärge laske end lollitada: arvutage töötajate ja konsultantide tegelikud kulud
Töötajate säilitamise strateegiad 101: töökohaõpe
Töötajate säilitamise strateegiad 101: töökohaõpe
AngularJSi õpetus: kohandatud direktiivide demüstifitseerimine
AngularJSi õpetus: kohandatud direktiivide demüstifitseerimine
Vilgas riistvara koos sisseehitatud tarkvaraarendusega
Vilgas riistvara koos sisseehitatud tarkvaraarendusega
 
Masinõppe manused: keerukate andmete lihtsustamine
Masinõppe manused: keerukate andmete lihtsustamine
Forexi algoritmiline kauplemine: praktiline lugu inseneridele
Forexi algoritmiline kauplemine: praktiline lugu inseneridele
Twitteri andmekaevandus: Pythoni abil suurandmete analüüsi juhend
Twitteri andmekaevandus: Pythoni abil suurandmete analüüsi juhend
Tehisintellekti investeeringute põhialus: põhitööde rajamine (I osa)
Tehisintellekti investeeringute põhialus: põhitööde rajamine (I osa)
ApeeScape'i nimekiri parimatest tasuta programmeerimisraamatutest
ApeeScape'i nimekiri parimatest tasuta programmeerimisraamatutest
Lemmik Postitused
  • mis on läheduse põhimõte
  • mis on cfo roll
  • sümboolse autentimise näited
  • porteri viis jõudu ostujõudu
  • proovige JavaScripti parimaid tavasid
  • kuidas masinõpet kasutada
Kategooriad
Projekti Juht Töö Tulevik Jaotatud Võistkonnad Tooteinimesed Ja Meeskonnad Andmeteadus Ja Andmebaasid Tehnoloogia Protsess Ja Tööriistad Veebi Kasutajaliides Tagumine Ots Nõuanded Ja Tööriistad

© 2021 | Kõik Õigused Kaitstud

apeescape2.com