15 research outputs found
Automated Refactoring of Legacy Java Software to Default Methods
Java 8 default methods, which allow interfaces to contain (instance) method implementations, are useful for the skeletal implementation software design pattern. However, it is not easy to transform existing software to exploit default methods as it requires analyzing complex type hierarchies, resolving multiple implementation inheritance issues, reconciling differences between class and interface methods, and analyzing tie-breakers (dispatch precedence) with overriding class methods to preserve type-correctness and confirm semantics preservation. In this paper, we present an efficient, fully-automated, type constraint-based refactoring approach that assists developers in taking advantage of enhanced interfaces for their legacy Java software. The approach features an extensive rule set that covers various corner-cases where default methods cannot be used. To demonstrate applicability, we implemented our approach as an Eclipse plug-in and applied it to 19 real-world Java projects, as well as submitted pull requests to popular GitHub repositories. The indication is that it is useful in migrating skeletal implementation methods to interfaces as default methods, sheds light onto the patternβs usage, and provides insight to language designers on how this new construct applies to existing software
Proactive Empirical Assessment of New Language Feature Adoption via Automated Refactoring: The Case of Java 8 Default Methods
Programming languages and platforms improve over time, sometimes resulting in
new language features that offer many benefits. However, despite these
benefits, developers may not always be willing to adopt them in their projects
for various reasons. In this paper, we describe an empirical study where we
assess the adoption of a particular new language feature. Studying how
developers use (or do not use) new language features is important in
programming language research and engineering because it gives designers
insight into the usability of the language to create meaning programs in that
language. This knowledge, in turn, can drive future innovations in the area.
Here, we explore Java 8 default methods, which allow interfaces to contain
(instance) method implementations.
Default methods can ease interface evolution, make certain ubiquitous design
patterns redundant, and improve both modularity and maintainability. A focus of
this work is to discover, through a scientific approach and a novel technique,
situations where developers found these constructs useful and where they did
not, and the reasons for each. Although several studies center around assessing
new language features, to the best of our knowledge, this kind of construct has
not been previously considered.
Despite their benefits, we found that developers did not adopt default
methods in all situations. Our study consisted of submitting pull requests
introducing the language feature to 19 real-world, open source Java projects
without altering original program semantics. This novel assessment technique is
proactive in that the adoption was driven by an automatic refactoring approach
rather than waiting for developers to discover and integrate the feature
themselves. In this way, we set forth best practices and patterns of using the
language feature effectively earlier rather than later and are able to possibly
guide (near) future language evolution. We foresee this technique to be useful
in assessing other new language features, design patterns, and other
programming idioms
Proactive Empirical Assessment of New Language Feature Adoption via Automated Refactoring: The Case of Java 8 Default Methods
Programming languages and platforms improve over time, sometimes resulting in new language features that offer many benefits. However, despite these benefits, developers may not always be willing to adopt them in their projects for various reasons. In this paper, we describe an empirical study where we assess the adoption of a particular new language feature. Studying how developers use (or do not use) new language features is important in programming language research and engineering because it gives designers insight into the usability of the language to create meaning programs in that language. This knowledge, in turn, can drive future innovations in the area. Here, we explore Java 8 default methods, which allow interfaces to contain (instance) method implementations.
Default methods can ease interface evolution, make certain ubiquitous design patterns redundant, and improve both modularity and maintainability. A focus of this work is to discover, through a scientific approach and a novel technique, situations where developers found these constructs useful and where they did not, and the reasons for each. Although several studies center around assessing new language features, to the best of our knowledge, this kind of construct has not been previously considered.
Despite their benefits, we found that developers did not adopt default methods in all situations. Our study consisted of submitting pull requests introducing the language feature to 19 real-world, open source Java projects without altering original program semantics. This novel assessment technique is proactive in that the adoption was driven by an automatic refactoring approach rather than waiting for developers to discover and integrate the feature themselves. In this way, we set forth best practices and patterns of using the language feature effectively earlier rather than later and are able to possibly guide (near) future language evolution. We foresee this technique to be useful in assessing other new language features, design patterns, and other programming idioms
Proactive Empirical Assessment of New Language Feature Adoption via Automated Refactoring: The Case of Java 8 Default Methods
Programming languages and platforms improve over time, sometimes resulting in new language features that offer many benefits. However, despite these benefits, developers may not always be willing to adopt them in their projects for various reasons. In this paper, we describe an empirical study where we assess the adoption of a particular new language feature. Studying how developers use (or do not use) new language features is important in programming language research and engineering because it gives designers insight into the usability of the language to create meaning programs in that language. This knowledge, in turn, can drive future innovations in the area. Here, we explore Java 8 default methods, which allow interfaces to contain (instance) method implementations.
Default methods can ease interface evolution, make certain ubiquitous design patterns redundant, and improve both modularity and maintainability. A focus of this work is to discover, through a scientific approach and a novel technique, situations where developers found these constructs useful and where they did not, and the reasons for each. Although several studies center around assessing new language features, to the best of our knowledge, this kind of construct has not been previously considered.
Despite their benefits, we found that developers did not adopt default methods in all situations. Our study consisted of submitting pull requests introducing the language feature to 19 real-world, open source Java projects without altering original program semantics. This novel assessment technique is proactive in that the adoption was driven by an automatic refactoring approach rather than waiting for developers to discover and integrate the feature themselves. In this way, we set forth best practices and patterns of using the language feature effectively earlier rather than later and are able to possibly guide (near) future language evolution. We foresee this technique to be useful in assessing other new language features, design patterns, and other programming idioms
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
Streaming APIs are becoming more pervasive in mainstream Object-Oriented programming languages and platforms. For example, the Stream API introduced in Java 8 allows for functional-like, MapReduce-style operations in processing both finite, e.g., collections, and infinite data structures. However, using this API efficiently involves subtle considerations such as determining when it is best for stream operations to run in parallel, when running operations in parallel can be less efficient, and when it is safe to run in parallel due to possible lambda expression side-effects. Also, streams may not run all operations in parallel depending on particular collectors used in reductions. In this paper, we present an automated refactoring approach that assists developers in writing efficient stream code in a semantics-preserving fashion. The approach, based on a novel data ordering and typestate analysis, consists of preconditions and transformations for automatically determining when it is safe and possibly advantageous to convert sequential streams to parallel, unorder or de-parallelize already parallel streams, and optimize streams involving complex reductions. The approach was implemented as a plug-in to the popular Eclipse IDE, uses the WALA and SAFE analysis frameworks, and was evaluated on 11 Java projects consisting of βΌ642K lines of code. We found that 57 of 157 candidate streams (36.31%) were refactorable, and an average speedup of 3.49 on performance tests was observed. The results indicate that the approach is useful in optimizing stream code to their full potential
Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams
Streaming APIs are becoming more pervasive in mainstream Object-Oriented programming languages. For example, the Stream API introduced in Java 8 allows for functional-like, MapReduce-style operations in processing both finite and infinite data structures. However, using this API efficiently involves subtle considerations like determining when it is best for stream operations to run in parallel, when running operations in parallel can be less efficient, and when it is safe to run in parallel due to possible lambda expression side-effects. In this paper, we present an automated refactoring approach that assists developers in writing efficient stream code in a semantics-preserving fashion. The approach, based on a novel data ordering and typestate analysis, consists of preconditions for automatically determining when it is safe and possibly advantageous to convert sequential streams to parallel and unorder or de-parallelize already parallel streams. The approach was implemented as a plug-in to the Eclipse IDE, uses the WALA and SAFE analysis frameworks, and was evaluated on 11 Java projects consisting of βΌ642K lines of code. We found that 57 of 157 candidate streams (36.31%) were refactorable, and an average speedup of 3.49 on performance tests was observed. The results indicate that the approach is useful in optimizing stream code to their full potential
An Empirical Study of Refactorings and Technical Debt in Machine Learning Systems
Machine Learning (ML), including Deep Learning (DL), systems, i.e., those with ML capabilities, are pervasive in todayβs data-driven society. Such systems are complex; they are comprised of ML models and many subsystems that support learning processes. As with other complex systems, ML systems are prone to classic technical debt issues, especially when such systems are long-lived, but they also exhibit debt specific to these systems. Unfortunately, there is a gap of knowledge in how ML systems actually evolve and are maintained. In this paper, we fill this gap by studying refactorings, i.e., source-to-source semantics-preserving program transformations, performed in real-world, open-source software, and the technical debt issues they alleviate. We analyzed 26 projects, consisting of 4.2 MLOC, along with 327 manually examined code patches. The results indicate that developers refactor these systems for a variety of reasons, both specific and tangential to ML, some refactorings correspond to established technical debt categories, while others do not, and code duplication is a major cross-cutting theme that particularly involved ML configuration and model code, which was also the most refactored. We also introduce 14 and 7 new ML-specific refactorings and technical debt categories, respectively, and put forth several recommendations, best practices, and anti-patterns. The results can potentially assist practitioners, tool developers, and educators in facilitating long-term ML system usefulness
Automated Evolution of Feature Logging Statement Levels Using Git Histories and Degree of Interest
Loggingβused for system events and security breaches to more informational yet essential aspects of software featuresβis pervasive. Given the high transactionality of todayβs software, logging effectiveness can be reduced by information overload. Log levels help alleviate this problem by correlating a priority to logs that can be later filtered. As software evolves, however, levels of logs documenting surrounding feature implementations may also require modification as features once deemed important may have decreased in urgency and vice-versa. We present an automated approach that assists developers in evolving levels of such (feature) logs. The approach, based on mining Git histories and manipulating a degree of interest (DOI) model, transforms source code to revitalize feature log levels based on the βinterestingnessβ of the surrounding code. Built upon JGit and Mylyn, the approach is implemented as an Eclipse IDE plug-in and evaluated on 18 Java projects with ~3 million lines of code and ~4K log statements. Our tool successfully analyzes 99.26% of logging statements, increases log level distributions by ~20%, identifies logs manually modified with a recall of ~80% and a level-direction match rate of ~87%, and increases the focus of logs in bug fix contexts ~83% of the time. Moreover, pull (patch) requests were integrated into large and popular open-source projects. The results indicate that the approach is promising in assisting developers in evolving feature log levels
ΠΡΡΡΠ°ΠΆΡΠ²Π°ΡΠ΅ Π·Π° Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎΡΡΠ° Π½Π° Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ ΠΊΠΎΠ΄ ΡΠΎ GPT (Generative Pre-Trained Transformer) Π·Π° Π·Π°Π΄Π°ΡΠΈ Π²ΠΎ ΡΠΎΡΡΠ²Π΅ΡΡΠΊΠΎΡΠΎ ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΡΡΠ²ΠΎ
ΠΡΠ·ΠΈΠΎΡ Π½Π°ΠΏΡΠ΅Π΄ΠΎΠΊ Π½Π° ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠ΅ Π·Π° ΠΌΠ°ΡΠΈΠ½ΡΠΊΠΎ ΡΡΠ΅ΡΠ΅ ΠΊΠΎΠΈ ΠΊΠΎΡΠΈΡΡΠ°Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π½Π°
ΠΏΡΠΈΡΠΎΠ΄Π΅Π½ ΡΠ°Π·ΠΈΠΊ ΠΏΡΠ΅Π΄ΠΈΠ·Π²ΠΈΠΊΠ° ΠΈΠ½ΡΠ΅ΡΠ΅Ρ Π·Π° Π½ΠΈΠ²Π½Π°ΡΠ° ΠΏΠΎΡΠ΅Π½ΡΠΈΡΠ°Π»Π½Π° ΠΏΡΠΈΠΌΠ΅Π½Π° Π·Π°
Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ ΠΊΠΎΠ΄ Π²ΠΎ ΠΎΠ±Π»Π°ΡΡΠ° ΡΠΎΡΡΠ²Π΅ΡΡΠΊΠΎΡΠΎ ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΡΡΠ²ΠΎ. ΠΠ²Π°Π° ΡΠ΅Π·Π° ΡΠ° ΠΈΡΠΏΠΈΡΡΠ²Π°
Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎΡΡΠ° Π½Π° GPT (ΠΠ΅Π½Π΅ΡΠ°ΡΠΈΠ²Π΅Π½ ΠΏΡΠ΅ΡΡ
ΠΎΠ΄Π½ΠΎ-ΡΡΠ΅Π½ΠΈΡΠ°Π½ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ΅Ρ)
ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠ΅ Π²ΠΎ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠ°ΡΠ΅ΡΠΎ Π½Π° Π·Π°Π΄Π°ΡΠΈΡΠ΅ Π·Π° ΠΊΠΎΠ΄ΠΈΡΠ°ΡΠ΅, ΠΎΡΠ΅Π½ΡΠ²Π°ΡΡΠΈ Π³ΠΎ
Π½ΠΈΠ²Π½ΠΈΠΎΡ ΠΏΠΎΡΠ΅Π½ΡΠΈΡΠ°Π» Π·Π° ΠΏΠΎΠ΄ΠΎΠ±ΡΡΠ²Π°ΡΠ΅ Π½Π° Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎΡΡΠ°, ΡΠΎΡΠ½ΠΎΡΡΠ° ΠΈ ΠΊΠ²Π°Π»ΠΈΡΠ΅ΡΠΎΡ Π½Π°
ΠΊΠΎΠ΄ΠΎΡ.
Π‘ΡΡΠ΄ΠΈΡΠ°ΡΠ° Π²ΠΊΠ»ΡΡΡΠ²Π° Π΄Π»Π°Π±ΠΈΠ½ΡΠΊΠ° Π°Π½Π°Π»ΠΈΠ·Π° Π½Π° ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠ΅ Π±Π°Π·ΠΈΡΠ°Π½ΠΈ Π½Π° GPT,
Π²ΠΊΠ»ΡΡΡΠ²Π°ΡΡΠΈ Π³ΠΈ GPT-3.5 ΠΈ GPT-4, ΠΈ Π³ΠΈ ΠΎΡΠ΅Π½ΡΠ²Π° Π½ΠΈΠ²Π½ΠΈΡΠ΅ ΠΏΠ΅ΡΡΠΎΡΠΌΠ°Π½ΡΠΈ Π²ΡΠ·
ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΡΠΊΠΈ ΡΠ°Π·ΠΈΡΠΈ ΠΈ Π·Π°Π΄Π°ΡΠΈ. Π’Π°Π° ΠΊΠΎΡΠΈΡΡΠΈ ΠΊΠ²Π°Π»ΠΈΡΠ°ΡΠΈΠ²Π½ΠΈ ΠΈ
ΠΊΠ²Π°Π½ΡΠΈΡΠ°ΡΠΈΠ²Π½ΠΈ ΠΌΠ΅ΡΠΊΠΈ ΠΈ ΡΠ²ΠΈΠ΄ΠΈ Π±Π°Π·ΠΈΡΠ°Π½ΠΈ Π½Π° Π°Π½ΠΊΠ΅ΡΠΈ Π·Π° Π΄Π° ΠΎΠ±Π΅Π·Π±Π΅Π΄ΠΈ ΡΠ΅ΠΎΠΏΡΠ°ΡΠ½Π°
ΠΏΡΠΎΡΠ΅Π½ΠΊΠ° Π·Π° Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎΡΡΠ° Π½Π° ΠΎΠ²ΠΈΠ΅ ΠΌΠΎΠ΄Π΅Π»ΠΈ Π²ΠΎ Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ΡΠΎ ΠΊΠΎΠ΄.
ΠΡΠ²ΠΈΡΠ½ΠΈΡΠ΅ Π½Π°ΠΎΠ΄ΠΈ ΡΡΠ³Π΅ΡΠΈΡΠ°Π°Ρ Π΄Π΅ΠΊΠ° ΠΈΠ°ΠΊΠΎ GPT ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠ΅ ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π°Π°Ρ ΠΏΠΎΡΠ΅Π½ΡΠΈΡΠ°Π»
Π·Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΡΡΠ²ΠΎ Π½Π° ΡΠΎΡΠ΅Π½, ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠΊΠΈ ΠΏΡΠ΅ΡΠΈΠ·Π΅Π½ ΠΊΠΎΠ΄ Π·Π° Π΄ΠΎΠ±ΡΠΎ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠΈΡΠ°Π½ΠΈ
Π·Π°Π΄Π°ΡΠΈ, Π½ΠΈΠ²Π½Π°ΡΠ° Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎΡΡ ΡΠ΅ Π½Π°ΠΌΠ°Π»ΡΠ²Π° ΠΊΠΎΠ³Π° ΡΠ΅ ΡΠΎΠΎΡΡΠ²Π°Π°Ρ ΡΠΎ Π΄Π²ΠΎΡΠΌΠΈΡΠ»Π΅Π½ΠΈ
ΠΈΠ»ΠΈ ΡΠ»ΠΎΠΆΠ΅Π½ΠΈ ΠΎΠΏΠΈΡΠΈ Π½Π° Π·Π°Π΄Π°ΡΠΈ. ΠΠ²ΠΈΠ΅ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠΈ Π³ΠΈ ΠΈΡΡΠ°ΠΊΠ½ΡΠ²Π°Π°Ρ ΠΈ ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈΡΠ΅ ΠΈ
ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΡΠ°ΡΠ° Π½Π° Π°Π»Π°ΡΠΊΠΈΡΠ΅ Π·Π° Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ ΠΊΠΎΠ΄ Π±Π°Π·ΠΈΡΠ°Π½ΠΈ Π½Π° GPT, ΡΡΠΎ ΡΠΊΠ°ΠΆΡΠ²Π°
Π½Π° ΠΏΠΎΡΡΠ΅Π±Π°ΡΠ° Π·Π° ΠΏΠΎΡΠΎΡΠΈΡΡΠΈΡΠΈΡΠ°Π½ΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΡΠΏΠΎΡΠΎΠ±Π½ΠΈ Π΄Π° ΡΠ΅ ΡΠΏΡΠ°Π²Π°Ρ ΡΠΎ
ΡΠ»ΠΎΠΆΠ΅Π½ΠΎΡΡΠ° Π½Π° ΡΠΎΡΡΠ²Π΅ΡΡΠΊΠΎΡΠΎ ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΡΡΠ²ΠΎ.
ΠΡΡΡΠ°ΠΆΡΠ²Π°ΡΠ΅ΡΠΎ, ΠΈΡΡΠΎ ΡΠ°ΠΊΠ°, Π³ΠΈ ΠΈΡΡΡΠ°ΠΆΡΠ²Π° ΠΈΠΌΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈΡΠ΅ Π½Π° Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ΡΠΎ ΠΊΠΎΠ΄
Π·Π°ΡΠ½ΠΎΠ²Π°Π½ΠΎ Π½Π° GPT Π²ΡΠ· ΡΠ°Π±ΠΎΡΠ½ΠΈΡΠ΅ ΡΠ΅ΠΊΠΎΠ²ΠΈ Π½Π° ΡΠΎΡΡΠ²Π΅ΡΡΠΊΠΎΡΠΎ ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΡΡΠ²ΠΎ,
Π΄ΠΈΡΠΊΡΡΠΈΡΠ°ΡΡΠΈ Π³ΠΈ ΠΌΠΎΠΆΠ½ΠΈΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ Π²ΠΎ ΡΠ»ΠΎΠ³ΠΈΡΠ΅ Π½Π° ΡΠΎΡΡΠ²Π΅ΡΡΠΊΠΈΡΠ΅ ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΠΈ.
ΠΠ½Π°Π»ΠΈΠ·ΠΈΡΠ°Π½ Π΅ ΠΏΠΎΡΠ΅Π½ΡΠΈΡΠ°Π»ΠΎΡ ΠΎΠ²ΠΈΠ΅ Π°Π»Π°ΡΠΊΠΈ Π·Π° Π²Π΅ΡΡΠ°ΡΠΊΠ° ΠΈΠ½ΡΠ΅Π»ΠΈΠ³Π΅Π½ΡΠΈΡΠ° Π΄Π°
ΠΈΠ·Π²ΡΡΡΠ²Π°Π°Ρ ΡΠ΅ΠΊΠΎΡΠ΄Π½Π΅Π²Π½ΠΈ Π·Π°Π΄Π°ΡΠΈ, ΡΠΎ ΡΡΠΎ ΡΠ΅ ΠΈΠΌ ΡΠ΅ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΠΈ Π½Π° ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΠΈΡΠ΅ Π΄Π° ΡΠ΅
ΡΠΎΠΊΡΡΠΈΡΠ°Π°Ρ Π½Π° Π΄ΠΈΠ·Π°ΡΠ½ Π½Π° Π²ΠΈΡΠΎΠΊΠΎ Π½ΠΈΠ²ΠΎ ΠΈ Π½Π° ΡΡΡΠ°ΡΠ΅Π³ΠΈΡΠΊΠΎ ΠΎΠ΄Π»ΡΡΡΠ²Π°ΡΠ΅.
ΠΡΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½ΠΎ, ΡΠ΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΠ°Π°Ρ ΠΏΡΠ΅Π΄ΠΈΠ·Π²ΠΈΡΠΈΡΠ΅, Π²ΠΊΠ»ΡΡΠΈΡΠ΅Π»Π½ΠΎ ΠΈ Π½Π΅ΠΎΠΏΡ
ΠΎΠ΄Π½ΠΎΡΡΠ° ΠΎΠ΄
4
ΡΠ΅ΠΌΠ΅Π»Π½ΠΎ ΡΠ΅ΡΡΠΈΡΠ°ΡΠ΅ ΠΈ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡΠ° Π½Π° ΠΊΠΎΠ΄ΠΎΡ Π³Π΅Π½Π΅ΡΠΈΡΠ°Π½ ΡΠΎ ΠΎΠ²ΠΈΠ΅ Π°Π»Π°ΡΠΊΠΈ ΠΈ
ΠΏΠΎΡΠ΅Π½ΡΠΈΡΠ°Π»Π½ΠΈΡΠ΅ Π΅ΡΠΈΡΠΊΠΈ ΠΈΠΌΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈ Π½Π° Π²Π΅ΡΡΠ°ΡΠΊΠ°ΡΠ° ΠΈΠ½ΡΠ΅Π»ΠΈΠ³Π΅Π½ΡΠΈΡΠ° Π²ΠΎ ΡΠ°Π·Π²ΠΎΡΠΎΡ Π½Π°
ΡΠΎΡΡΠ²Π΅ΡΠΎΡ.
ΠΠ²Π°Π° ΡΡΡΠ΄ΠΈΡΠ° ΠΏΡΠΈΠ΄ΠΎΠ½Π΅ΡΡΠ²Π° Π·Π° ΡΠ°Π·Π±ΠΈΡΠ°ΡΠ΅ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΡΠ½ΠΈΡΠ΅ Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈ ΠΈ
ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΡΠ°ΡΠ° Π½Π° ΠΠ Π²ΠΎ ΡΠ°Π·Π²ΠΎΡΠΎΡ Π½Π° ΡΠΎΡΡΠ²Π΅Ρ ΠΈ ΠΈΠ·Π³Π»Π΅Π΄ΠΈΡΠ΅ Π·Π° ΠΏΠΎΠ΄ΠΎΠ±ΡΡΠ²Π°ΡΠ΅. Π‘Π΅
ΠΏΠΎΡΠ²ΡΠ΄ΡΠ²Π° Π΄Π΅ΠΊΠ° ΠΈΠ°ΠΊΠΎ ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠ΅ Π±Π°Π·ΠΈΡΠ°Π½ΠΈ Π½Π° GPT ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π°Π°Ρ Π·Π½Π°ΡΠΈΡΠ΅Π»Π΅Π½
ΠΏΠΎΡΠ΅Π½ΡΠΈΡΠ°Π» Π²ΠΎ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠ°ΡΠ΅ΡΠΎ Π½Π° ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ½ΠΈΡΠ΅ Π°ΡΠΏΠ΅ΠΊΡΠΈ Π½Π° ΡΠΎΡΡΠ²Π΅ΡΡΠΊΠΎΡΠΎ
ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΡΡΠ²ΠΎ, ΡΠΎΠ²Π΅ΡΠΊΠΈΠΎΡ ΠΏΡΠΈΠ΄ΠΎΠ½Π΅Ρ ΠΈ Π½Π°Π΄Π·ΠΎΡΠΎΡ ΠΎΡΡΠ°Π½ΡΠ²Π°Π°Ρ ΠΊΠ»ΡΡΠ½ΠΈ Π·Π° ΡΠΏΡΠ°Π²ΡΠ²Π°ΡΠ΅
ΡΠΎ ΡΠ»ΠΎΠΆΠ΅Π½ΠΈ, ΠΊΡΠ΅Π°ΡΠΈΠ²Π½ΠΈ ΠΈ Π΄Π²ΠΎΡΠΌΠΈΡΠ»Π΅Π½ΠΈ Π·Π°Π΄Π°ΡΠΈ.
ΠΠ»ΡΡΠ½ΠΈ Π·Π±ΠΎΡΠΎΠ²ΠΈ:
ΠΠ΅ΡΡΠ°ΡΠΊΠ° ΠΈΠ½ΡΠ΅Π»ΠΈΠ³Π΅Π½ΡΠΈΡΠ°, ΠΌΠ°ΡΠΈΠ½ΡΠΊΠΎ ΡΡΠ΅ΡΠ΅, ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π½Π° ΠΏΡΠΈΡΠΎΠ΄Π½ΠΈ ΡΠ°Π·ΠΈΡΠΈ,
Π°Π²ΡΠΎΠΌΠ°ΡΡΠΊΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°ΡΠ΅, ΠΊΠ²Π°Π»ΠΈΡΠ΅Ρ Π½Π° ΠΊΠΎΠ΄, Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎΡΡ Π½Π° ΡΠ°Π±ΠΎΡΠ½ΠΈΠΎΡ ΡΠ΅ΠΊ, Π΅ΡΠΈΠΊΠ°
Π²ΠΎ Π²Π΅ΡΡΠ°ΡΠΊΠ°ΡΠ° ΠΈΠ½ΡΠ΅Π»ΠΈΠ³Π΅Π½ΡΠΈΡΠ°