1
0
mirror of synced 2025-12-19 18:10:59 -05:00

Allow articles with missing shortTitles to appear on home page (#54389)

This commit is contained in:
Hector Alfaro
2025-02-12 15:31:38 -05:00
committed by GitHub
parent 7b14d4b401
commit bb142f9ba2
36 changed files with 82 additions and 29 deletions

View File

@@ -0,0 +1,151 @@
---
title: Decoupling business logic from UI components
shortTitle: Decoupling business logic
intro: '{% data variables.product.prodname_copilot_chat_short %} can help you separate your business logic from your user interface code, making it easier to maintain and scale your application.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/decoupling-business-logic-from-ui-components
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Advanced
octicon: rocket
topics:
- Copilot
---
In many front-end frameworks, business logic can become embedded within user interface (UI) components, making the code hard to maintain or extend, especially as the application grows.
{% data variables.product.prodname_copilot_chat_short %} can help you refactor your code to extract business logic into separate services or state management solutions. This allows the business logic to be reused across different UI components. It also makes the code easier to scale by separating concerns and reducing interdependencies, and it simplifies unit testing by allowing business logic to be tested independently from UI components.
## Example scenario
In this JavaScript code, the `Counter` component configures the business logic for the component and also defines UI code for using the component in a web page.
```javascript
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const increment = () => {
if (count >= 10) {
alert('Count cannot exceed 10');
return;
}
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
export default Counter;
```
## Example prompt
`Use Redux to separate the UI code from the Counter component in this code.`
## Example response
{% data variables.product.prodname_copilot_short %} provides step-by-step instructions for refactoring the code.
The suggested changes refactor the `Counter` component to use Redux for state management. This includes setting up a Redux store with an initial state and a reducer, defining an increment action, and modifying the `Counter` component to connect to the Redux store. Finally, the application is wrapped with a `Provider` component to make the Redux store available to the `Counter` component. This separates the UI logic from state management.
The proposed changes separate the code into five separate files.
> [!NOTE] {% data variables.product.prodname_copilot_chat_short %} responses are non-deterministic, so you may get a different response from the one described here.
### actions.js
```javascript
export const increment = () => ({
type: 'INCREMENT'
});
```
### reducer.js
```javascript
const initialState = {
count: 0
};
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
if (state.count >= 10) {
alert('Count cannot exceed 10');
return state;
}
return {
...state,
count: state.count + 1
};
default:
return state;
}
};
export default counterReducer;
```
### store.js
```javascript
import { createStore } from 'redux';
import counterReducer from './reducer';
const store = createStore(counterReducer);
export default store;
```
### counter.js
```javascript
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './actions';
const Counter = () => {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(increment())}>Increment</button>
</div>
);
};
export default Counter;
```
### index.js
```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './counter';
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('root')
);
```
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,241 @@
---
title: 'Fixing database deadlocks or data integrity issues'
shortTitle: Fixing database deadlocks
intro: '{% data variables.product.prodname_copilot_chat_short %} can help you avoid code that causes slow or blocked database operations, or tables with missing or incorrect data.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/fixing-database-deadlocks-or-data-integrity-issues
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Advanced
octicon: rocket
topics:
- Copilot
---
Complex database operationsparticularly those involving transactionscan lead to deadlocks or data inconsistencies that are hard to debug.
{% data variables.product.prodname_copilot_chat_short %} can help by identifying points in a transaction where locking or deadlocks could occur, and can suggest best practices for transaction isolation or deadlock resolution, such as adjusting locking strategies or handling deadlock exceptions gracefully.
> [!NOTE] The responses shown in this article are examples. {% data variables.product.prodname_copilot_chat_short %} responses are non-deterministic, so you may get different responses from the ones shown here.
## Avoiding simultaneous updates on interdependent rows
When two or more transactions attempt to update the same rows in a database table, but in different orders, it can cause a circular wait condition.
### Example scenario
The following SQL snippet updates one row of a table, then performs an operation that takes several seconds, then updates another row in the same table. This is problematic because the transaction locks the `id = 1` row for several seconds before the transaction completes, releasing the lock. If another transaction starts during this time that performs a similar operation, but locks the `id = 2` row first, so that it can update the row, and then attempts to lock the `id = 1` row, then both transactions will be left waiting for the other to complete, resulting in deadlock.
```sql
BEGIN TRANSACTION;
UPDATE my_table SET value = 'Some value' WHERE id = 301;
-- Simulate a process taking 5 seconds:
WAITFOR DELAY '00:00:05';
UPDATE my_table SET value = 'Another value' WHERE id = 127;
COMMIT TRANSACTION;
```
### Example prompt 1
You can check whether there are any problems with this transaction.
In the editor, select the transaction code, then ask {% data variables.product.prodname_copilot_chat_short %}:
`Is this transaction good?`
### Example response 1
{% data variables.product.prodname_copilot_short %} tells you that "the transaction in your SQL code is generally fine," but lists some things you may want to consider: lock duration, error handling, and concurrency. It mentions that "the transaction holds locks for an extended period, potentially leading to blocking or deadlocks." The response also includes revised code that adds error handling.
In this case, you decide not to add error handling. Right now you want to address the potential for deadlocks.
### Example prompt 2
Enter this follow-up prompt:
`How can I rewrite this code to reduce the chance of deadlock to a minimum while not adversely affecting performance. Tell me anything else I can do to avoid a deadlock. Note: I don't want to add error handling at this time.`
### Example response 2
{% data variables.product.prodname_copilot_short %} gives the following advice:
> * **Order of Access:** Ensure that all transactions access tables and rows in the same order.
> * **Keep Transactions Short:** Minimize the time a transaction holds locks.
> * **Use Appropriate Isolation Levels:** Use the lowest isolation level that meets your requirements.
>
> Here is a revised version of your code:
```sql
BEGIN TRANSACTION;
-- Update the rows in a consistent order
UPDATE my_table SET value = 'Another value' WHERE id = 127;
UPDATE my_table SET value = 'Some value' WHERE id = 301;
-- Simulate a process taking 5 seconds:
WAITFOR DELAY '00:00:05';
COMMIT TRANSACTION;
```
## Avoiding non-index searches
Searching table columns that have not been indexed will typically result in a full table scan. This can be very slow and resource-intensive, increasing the likelihood of performance bottlenecks.
### Example scenario
The following SQL will result in a full table scan if `some_column` is not indexed:
```sql
BEGIN TRANSACTION;
SELECT * FROM my_table WHERE some_column = 'some_value';
-- More actions here, then:
COMMIT TRANSACTION;
```
### Example prompt
Asking {% data variables.product.prodname_copilot_short %} the following question will usually reveal the potential problem.
`How can I optimize this transaction?`
### Example response
{% data variables.product.prodname_copilot_short %} gives some advice, and mentions that the column should be indexed:
> To optimize the transaction, you should ensure that the transaction is as short as possible to reduce locking and improve performance. Here are a few tips:
>
> 1. **Minimize the work done in the transaction:** Only include the necessary operations within the transaction.
> 1. **Use appropriate indexes:** Ensure that the columns used in the WHERE clause are indexed.
> 1. **Avoid long-running transactions:** Keep the transaction duration short to avoid locking issues.
The suggested code in the response includes the SQL command for indexing the column:
```sql
`CREATE INDEX idx_some_column ON my_table(some_column);`
```
## Avoiding long-running transactions
It's important to avoid long-running queries and transactions, where possible, as these can severely degrade performance and cause bottlenecks for other operations. Additionally, they can consume significant memory and log space, making your application more prone to failure in high-load environments.
### Example scenario
The following SQL creates new rows in `target_table`, containing data from selected fields of rows in `source_table` where various conditions are met. If `source_table` is extremely large this may result in a long-running transaction.
```sql
BEGIN TRANSACTION;
INSERT INTO target_table (first_name, last_name, email, dept, role, hire_date)
SELECT first_name, last_name, email, department, job_title, start_date
FROM source_table
WHERE (department = 'Engineering' AND (salary > 95000 OR grade > 5))
OR (department = 'Marketing' AND performance_rating = 'Excellent');
COMMIT;
```
### Example prompt
You can ask {% data variables.product.prodname_copilot_short %} whether it's possible to avoid long-running transactions.
`source_table is an extremely large table. Without altering the table, how can I ensure this SQL doesn't become a long-running query, that blocks other operations?`
### Example response
{% data variables.product.prodname_copilot_short %} suggests the following strategies:
* **Batch Processing:** Process the data in smaller batches instead of a single large transaction. This can be done using a loop with a limit and offset.
* **Indexing:** Ensure that the columns used in the `WHERE` clause (`department`, `salary`, `grade`, and `performance_rating`) are indexed to speed up the query.
* **Locking:** Use row-level locking to avoid locking the entire table.
It supplies the following example of how you can implement batch processing. This SQL processes the data in batches of 1000 rows at a time, reducing the load on the database and preventing long-running transactions.
```sql
DECLARE @BatchSize INT = 1000;
DECLARE @Offset INT = 0;
DECLARE @RowCount INT;
SET @RowCount = @BatchSize;
WHILE @RowCount = @BatchSize
BEGIN
BEGIN TRANSACTION;
INSERT INTO target_table (first_name, last_name, email, dept, role, hire_date)
SELECT first_name, last_name, email, department, job_title, start_date
FROM source_table
WHERE (department = 'Engineering' AND salary > 95000)
OR (department = 'Engineering' AND years_of_experience > 5)
OR (department = 'Marketing' AND performance_rating = 'Excellent');
ORDER BY primary_key_column
OFFSET @Offset ROWS FETCH NEXT @BatchSize ROWS ONLY;
SET @RowCount = @@ROWCOUNT;
SET @Offset = @Offset + @BatchSize;
COMMIT;
END;
```
{% data variables.product.prodname_copilot_short %} tells you to replace `primary_key_column` in the suggested code with the name of the actual primary key column of `source_table`.
## Avoiding data integrity issues
It's important that the information in your databases remains accurate, consistent, and complete. Poorly designed queries can result in missing or incorrect data.
### Example scenario
The following SQL transaction deletes an employee record and creates a deletion log. However, it's possible for the `DELETE` operation to succeed and the `INSERT` operation to fail, in which case there is no log record for the deletion.
```sql
BEGIN TRANSACTION;
DELETE FROM employees
WHERE employee_id = 101;
INSERT INTO deletion_log (employee_id, deletion_date, reason)
VALUES (101, GETDATE(), 'Voluntary Resignation');
COMMIT TRANSACTION;
```
### Example prompt
`How can I ensure that the DELETE and INSERT operations are only performed if both succeed?`
{% data variables.product.prodname_copilot_short %} tells you that you achieve this by using a transaction with error handling. It gives the following example using SQL Server's `TRY...CATCH` construct:
```sql
BEGIN TRY
BEGIN TRANSACTION;
DELETE FROM employees
WHERE employee_id = 101;
INSERT INTO deletion_log (employee_id, deletion_date, reason)
VALUES (101, GETDATE(), 'Voluntary Resignation');
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
-- Handle the error, e.g., log it or re-throw
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;
```
The suggested code ensures that if either the `DELETE` or `INSERT` operation fails, the transaction is rolled back and no changes are made to the database.
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,69 @@
---
title: Fixing lint errors
shortTitle: Lint errors
intro: '{% data variables.product.prodname_copilot_chat_short %} can suggest ways to fix issues identified by a code linter.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/fixing-lint-errors
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Intermediate
octicon: rocket
topics:
- Copilot
---
It's good practice to use a linter to check your code for potential errors, style violations, or deviations from best practices. Linters can help you to catch bugs early, improve the readability of your code, and ensure that your code is consistent and maintainable.
## Example scenario
You have run a linter on your code and it has identified some issues that need to be fixed. Rather than fixing these manually, you can ask {% data variables.product.prodname_copilot_chat_short %} to fix them for you.
## Example prompts
* Select all of the code in the editor, then type:
`Fix the lint errors`
* You can specify a particular set of coding guidelines for a language, such as PEP8 for Python:
`Use PEP8 to fix the lint errors`
* If you have a local file that defines your coding conventions and rules, you can drag the file into the chat window to add it as an attachment, then type:
`Use the attached style guide to fix the lint errors`
* Alternatively, you can ask {% data variables.product.prodname_copilot_chat_short %} to fix only a specific type of lint error:
`Make sure all functions use snake_case naming style`
## Example response
{% data variables.product.prodname_copilot_short %} tells you what needs to be changed, and then gives you the corrected code. You should review the suggested code thoroughly before using it. The code that {% data variables.product.prodname_copilot_short %} suggests may not fix all of the issues identified by your linter, so you should always run the linter again if you choose to use the suggested code.
Linting issues that {% data variables.product.prodname_copilot_short %} can help you fix include:
* Adding necessary imports that are missing.
* Removing imports that are not used in the code.
* Splitting import statements into separate lines.
* Using method and function names that follow style guidelines.
* Adding spaces around operators.
* Ensuring consistent indentation.
* Removing trailing whitespace.
* Splitting multiple statements that are on a single line into separate lines.
* Breaking long line into multiple lines.
* Removing unused variables.
* Adding or removing blank lines to adhere to style guidelines.
* Adding docstrings to functions, classes, and modules.
* Removing code that will never be executed.
* Ensuring that all return statements in a function either return a value or none.
* Reducing or eliminating the use of global variables.
* Ensuring that functions are called with the correct number and type of arguments.
* Ensuring that comments are placed correctly and are meaningful.
* Replacing print statements with proper logging.
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,187 @@
---
title: Handling cross-cutting concerns
shortTitle: Cross-cutting concerns
intro: '{% data variables.product.prodname_copilot_chat_short %} can help you avoid code that relates to a concern other than the core concern of the method or function in which the code is located.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/handling-cross-cutting-concerns
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Intermediate
octicon: rocket
topics:
- Copilot
---
Cross-cutting concerns are aspects of a program that affect multiple parts of the system, such as logging, security, data validation, and error handling. They can become scattered throughout a codebase, leading to code duplication and maintenance challenges.
{% data variables.product.prodname_copilot_chat_short %} can help refactor cross-cutting concerns by suggesting the implementation of Aspect-Oriented Programming (AOP) practices or using decorators and middleware patterns to centralize these concerns in a modular, maintainable way.
## Example scenario
Imagine you have a Python project that contains multiple service files in which logging occurs. The information that gets logged is defined within each of the individual service files. If the application is modified or extended in future, this design could lead to inconsistency in the content and style of log entries. You can consolidate and centralize the logging behavior to avoid this being distributed across your project.
Here are three files from our example project: the entry point file (`main.py`), the log message configuration file (`logging_config.py`), and one of the service files (`order_service.py`). The example service file shows how log information is defined alongside the business logic for a particular part of the application.
### main.py
```python
import logging
from logging_config import setup_logging
from payment_service import PaymentService
from order_service import OrderService
from shipping_service import ShippingService
from inventory_service import InventoryService
from notification_service import NotificationService
def main():
setup_logging()
payment_service = PaymentService()
order_service = OrderService()
shipping_service = ShippingService()
inventory_service = InventoryService()
notification_service = NotificationService()
# Example usage
payment_service.process_payment({"amount": 100, "currency": "USD"})
order_service.place_order({"item": "Book", "quantity": 1})
shipping_service.ship_order({"item": "Book", "quantity": 1})
inventory_service.update_inventory("Book", -1)
notification_service.send_notification("Order has been placed and shipped.")
if __name__ == "__main__":
main()
```
### logging_config.py
```python
import logging
def setup_logging():
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
```
### order_service.py
```python
import logging
class OrderService:
def __init__(self):
self.logger = logging.getLogger(__name__)
def place_order(self, order):
self.logger.info("Entering place_order method.")
try:
# In here would be the business logic for placing an order
# ...
self.logger.info("Order placed successfully.")
except Exception as e:
self.logger.error(f"Error in place_order method: {e}")
raise
finally:
self.logger.info("Exiting place_order method.")
```
## Example prompt
Open the project workspace in {% data variables.product.prodname_vscode_shortname %} or {% data variables.product.prodname_vs %} and enter the following prompt in the {% data variables.product.prodname_copilot_chat_short %} view.
`@workspace Refactor this project by using AOP to avoid logging that has cross-cutting concerns`
> [!NOTE]
> The `@workspace` chat participant in {% data variables.product.prodname_vscode_shortname %} and {% data variables.product.prodname_vs %} provides {% data variables.product.prodname_copilot_short %} with context about all of the code in your workspace. You can use `@workspace` when you want {% data variables.product.prodname_copilot_short %} to consider the structure of your project and how different parts of your code interact. If you're using a JetBrains IDE, use `@project` rather than `@workspace`.
## Example response
{% data variables.product.prodname_copilot_short %} responds as follows.
{% data reusables.copilot.example-prompts.response-is-an-example %}
> To refactor this project using Aspect-Oriented Programming (AOP) to handle logging as a cross-cutting concern, you can use a library like `aspectlib`. Here is how you can do it:
>
> 1. Install `aspectlib`:
>
> `pip install aspectlib`
>
> 1. Create an aspect for logging in a new file called `logging_aspect.py`:
>
> ```python
> import aspectlib
> import logging
>
> @aspectlib.Aspect(bind=True)
> def log_method_call(cutpoint, *args, **kwargs):
> logger = logging.getLogger()
> method_name = cutpoint.__name__
> logger.info(f"Entering method: {method_name}")
> try:
> result = yield aspectlib.Proceed
> logger.info(f"Method {method_name} executed successfully.")
> return result
> except Exception as e:
> logger.error(f"Error in method {method_name}: {e}")
> raise
> finally:
> logger.info(f"Exiting method: {method_name}")
> ```
>
> 1. Apply the aspect to the service methods in `main.py`:
>
> ```python
> import logging
> from logging_config import setup_logging
> from payment_service import PaymentService
> from order_service import OrderService
> from shipping_service import ShippingService
> from inventory_service import InventoryService
> from notification_service import NotificationService
> from logging_aspect import log_method_call
> import aspectlib
>
> def main():
> setup_logging()
>
> # Apply logging aspect to service methods
> aspectlib.weave(PaymentService.process_payment, log_method_call)
> aspectlib.weave(OrderService.place_order, log_method_call)
> aspectlib.weave(ShippingService.ship_order, log_method_call)
> aspectlib.weave(InventoryService.update_inventory, log_method_call)
> aspectlib.weave(NotificationService.send_notification, log_method_call)
>
> payment_service = PaymentService()
> order_service = OrderService()
> shipping_service = ShippingService()
> inventory_service = InventoryService()
> notification_service = NotificationService()
>
> # Example usage
> payment_service.process_payment({"amount": 100, "currency": "USD"})
> order_service.place_order({"item": "Book", "quantity": 1})
> shipping_service.ship_order({"item": "Book", "quantity": 1})
> inventory_service.update_inventory("Book", -1)
> notification_service.send_notification("Order has been placed and shipped.")
>
> if __name__ == "__main__":
> main()
> ```
{% data variables.product.prodname_copilot_short %} then tells you to remove the logging code from all of the service classes, and gives you the code for the revised files. For example, this is the revised version of `order_service.py`:
```python
class OrderService:
def place_order(self, order):
# In here would be the business logic for placing an order
# ...
pass
```
In the refactored version of the project, the same logging operations are performed, but the logging code is centralized in a single file.
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,277 @@
---
title: 'Improving code readability and maintainability'
shortTitle: Improve code readability
intro: '{% data variables.product.prodname_copilot_chat_short %} can suggest ways to make your code easier to understand and maintain.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/improving-code-readability-and-maintainability
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Simple
octicon: rocket
topics:
- Copilot
---
Code with poor readability is difficult for other developers to maintain and extend. {% data variables.product.prodname_copilot_chat_short %} can help in a number of ways. For example, by:
* [Suggesting improvements to variable names](#improving-variable-names)
* [Avoiding sequential conditional checks](#avoiding-sequential-conditional-checks)
* [Reducing nested logic](#reducing-nested-logic)
* [Splitting large methods into smaller, more readable ones](#splitting-up-large-methods)
Documenting your code is another way to improve the maintainability of your code. For information about using {% data variables.product.prodname_copilot_chat_short %} to help you add useful comments to your code, see the example prompts in [Documenting code](/copilot/copilot-chat-cookbook/documenting-code).
> [!NOTE] The responses shown in this article are examples. {% data variables.product.prodname_copilot_chat_short %} responses are non-deterministic, so you may get different responses from the ones shown here.
## Improving variable names
Descriptive variable names and parameter names make it easier to understand their purpose.
### Example scenario
This JavaScript code logs a message about a person's age to the console. The abstract parameter names make it difficult to understand the purpose of the code.
```javascript
function logPersonsAge(a, b, c) {
if (c) {
console.log(a + " is " + b + " years old.");
} else {
console.log(a + " does not want to reveal their age.");
}
}
```
### Example prompt
In the editor, select the function you want to change, then ask {% data variables.product.prodname_copilot_chat_short %}:
`Improve the variable names in this function`
### Example response
{% data variables.product.prodname_copilot_short %} suggests descriptive variable names.
```javascript
function logPersonAge(name, age, revealAge) {
if (revealAge) {
console.log(name + " is " + age + " years old.");
} else {
console.log(name + " does not want to reveal their age.");
}
}
```
## Avoiding sequential conditional checks
`if...else` chains can be difficult to read, especially when they are long.
### Example scenario
This Python code prints the sound that various animals make, if defined, or "Unknown animal" if the animal type is not recognized. However, the chain of `if...else` statements makes the code inefficient and cumbersome.
```python
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class Bird(Animal):
def speak(self):
return "Tweet!"
def animal_sound(animal_type):
if animal_type == "dog":
return Dog().speak()
elif animal_type == "cat":
return Cat().speak()
elif animal_type == "bird":
return Bird().speak()
else:
return "Unknown animal"
print(animal_sound("dog"))
print(animal_sound("cat"))
print(animal_sound("bird"))
print(animal_sound("fish"))
```
### Example prompt
`Simplify this code. Avoid using if/else chains but retain all function return values.`
### Example response
{% data variables.product.prodname_copilot_short %} suggests using a dictionary to map the animal types to their corresponding classes.
```python
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class Bird(Animal):
def speak(self):
return "Tweet!"
def animal_sound(animal_type):
animals = {
"dog": Dog,
"cat": Cat,
"bird": Bird
}
animal_class = animals.get(animal_type, Animal)
return animal_class().speak() if animal_class != Animal else "Unknown animal"
print(animal_sound("dog"))
print(animal_sound("cat"))
print(animal_sound("bird"))
print(animal_sound("fish"))
```
## Reducing nested logic
Deeply nested structures can make the code hard to follow, making it difficult to modify or extend the logic of the code in future.
### Example scenario
This Ruby code prints information about a user account based on three parameters. The use of nested `if...else` statements makes the code unnecessarily complex.
```ruby
def determine_access(user_role, has_permission, is_active)
if user_role == "admin"
if has_permission
if is_active
"Active admin account with full access."
else
"Inactive admin account."
end
else
"Admin account lacks necessary permissions."
end
else
"Access denied."
end
end
puts determine_access("admin", true, true)
puts determine_access("admin", true, false)
puts determine_access("admin", false, true)
puts determine_access("user", true, true)
```
### Example prompt
`Rewrite this code to avoid the nested if/else statements`
### Example response
{% data variables.product.prodname_copilot_short %} suggests using guard clauses to handle the conditions early and return the appropriate messages.
```ruby
def determine_access(user_role, has_permission, is_active)
return "Access denied." unless user_role == "admin"
return "Admin account lacks necessary permissions." unless has_permission
return "Inactive admin account." unless is_active
"Active admin account with full access."
end
puts determine_access("admin", true, true)
puts determine_access("admin", true, false)
puts determine_access("admin", false, true)
puts determine_access("user", true, true)
```
## Splitting up large methods
It can be difficult to grasp exactly what a method or function does if it is too long, making it difficult to maintain. Methods or functions that perform multiple tasks may not be reusable in other contexts. It may also be difficult to test each task in isolation.
### Example scenario
This Java method processes a customer order and prints a message. It performs multiple tasks in a single method.
```java
public void processOrder(Order order) {
if (order == null || order.getItems().isEmpty()) {
throw new IllegalArgumentException("Order is invalid.");
}
double totalPrice = 0.0;
for (Item item : order.getItems()) {
totalPrice += item.getPrice() * item.getQuantity();
}
order.setTotalPrice(totalPrice);
if (totalPrice > 0) {
order.setStatus("Processed");
} else {
order.setStatus("Pending");
}
System.out.println("Order for customer " + order.getCustomerName() + " has been processed. Total price: " + totalPrice);
}
```
### Example prompt
`How could the processOrder method be refactored to be more useful and easier to maintain`
### Example response
{% data variables.product.prodname_copilot_short %} suggests breaking this method down into smaller, more focused methods.
```java
public void processOrder(Order order) {
validateOrder(order);
double totalPrice = calculateTotalPrice(order);
updateOrderStatus(order, totalPrice);
printOrderSummary(order, totalPrice);
}
private void validateOrder(Order order) {
if (order == null || order.getItems().isEmpty()) {
throw new IllegalArgumentException("Order is invalid.");
}
}
private double calculateTotalPrice(Order order) {
double totalPrice = 0.0;
for (Item item : order.getItems()) {
totalPrice += item.getPrice() * item.getQuantity();
}
order.setTotalPrice(totalPrice);
return totalPrice;
}
private void updateOrderStatus(Order order, double totalPrice) {
if (totalPrice > 0) {
order.setStatus("Processed");
} else {
order.setStatus("Pending");
}
}
private void printOrderSummary(Order order, double totalPrice) {
System.out.println("Order for customer " + order.getCustomerName() + " has been processed. Total price: " + totalPrice);
}
```
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,20 @@
---
title: Refactoring code
intro: 'Discover ways that you can use {% data variables.product.prodname_copilot %} to refactor your code.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code
versions:
feature: copilot
topics:
- Copilot
children:
- /improving-code-readability-and-maintainability
- /fixing-lint-errors
- /refactoring-for-performance-optimization
- /refactoring-to-implement-a-design-pattern
- /refactoring-data-access-layers
- /decoupling-business-logic-from-ui-components
- /handling-cross-cutting-concerns
- /simplifying-complex-inheritance-hierarchies
- /fixing-database-deadlocks-or-data-integrity-issues
---

View File

@@ -0,0 +1,129 @@
---
title: Refactoring data access layers
shortTitle: Data access layers
intro: '{% data variables.product.prodname_copilot_chat_short %} can suggest ways to decouple your data access code from your business logic, making an application easier to maintain and scale.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/refactoring-data-access-layers
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Advanced
octicon: rocket
topics:
- Copilot
---
Hardcoded SQL queries and tightly coupled data access code can make it difficult to scale or switch databases, and they often lead to repeated logic.
{% data variables.product.prodname_copilot_chat_short %} can recommend implementing a repository pattern or data access layer that abstracts database interactions, making the code more modular and reducing redundancy. It can also help refactor SQL queries into optimized versions, improving performance and maintainability.
> [!NOTE] The responses described in this article are examples. {% data variables.product.prodname_copilot_chat_short %} responses are non-deterministic, so you may get different responses from the ones shown here.
## Example scenario
This Python code connects to a SQLite database, retrieves a user record, and returns the user data. However, it fails to abstract the database connection logic and uses a hardcoded query that's vulnerable to SQL injection.
```python
import sqlite3
def get_user_by_id(user_id):
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute(f"SELECT display_name FROM users WHERE id = {user_id}")
user = cursor.fetchone()
conn.close()
return user
```
## Example prompt 1
You can start by asking {% data variables.product.prodname_copilot_short %} a general question about how to improve the code.
`How can I improve this code to make it safe and easier to update and expand? List possible improvements but don't show revised code.`
## Example response 1
{% data variables.product.prodname_copilot_short %} makes several suggestions for improving the code:
* Abstract the database connection details.
* Use parameterized queries to prevent SQL injection.
* Use a context manager to ensure that the database connection is properly closed if an error occurs.
* Add error handling.
## Example prompt 2
You can use the response to your first prompt to write a more specific prompt.
`Rewrite this code to make it more scalable and easier to maintain. Use a context manager. Avoid hardcoded SQL queries and tightly coupled data access code. Instead, use a repository pattern to abstract database interactions and make the code more modular and reusable. Where possible optimize the code to improve performance. Include error trapping, and make sure the code is not vulnerable to SQL injection.`
## Example response 2
{% data variables.product.prodname_copilot_short %} suggests splitting the code into separate files, each with a specific purpose. It also provides example code for returning a user's details.
The suggested changes implement a repository pattern and use parameterized queries to avoid SQL injection.
```python
# database.py
import sqlite3
class Database:
def __init__(self, db_path):
self.db_path = db_path
def __enter__(self):
self.conn = sqlite3.connect(self.db_path)
self.cursor = self.conn.cursor()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type or exc_val or exc_tb:
self.conn.rollback()
else:
self.conn.commit()
self.conn.close()
# user_repository.py
class UserRepository:
def __init__(self, db):
self.db = db
def get_user_by_id(self, user_id):
try:
self.db.cursor.execute("SELECT display_name FROM users WHERE id = ?", (user_id,))
user = self.db.cursor.fetchone()
return user
except sqlite3.Error as e:
print(f"An error occurred: {e}")
return None
# main.py
from database import Database
from user_repository import UserRepository
def get_user_by_id(user_id):
with Database('database.db') as db:
user_repo = UserRepository(db)
return user_repo.get_user_by_id(user_id)
# Example usage
if __name__ == "__main__":
user = get_user_by_id(1)
if user:
print(user)
else:
print("User not found or an error occurred.")
```
The revised code improves on the original in several ways:
* The code now implements a basic data access layer.
* The `Database` class handles the connection to the SQLite database, implementing the context manager protocol with the `__enter__` and `__exit__` methods. This ensures that the database connection is properly managed, including committing transactions and closing the connection.
* The `UserRepository` class encapsulates the logic for accessing user data.
* Values for the queries are parameterized to prevent SQL injection.
* Errors are caught, with details printed to the console.
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,95 @@
---
title: Refactoring for performance optimization
shortTitle: Performance optimization
intro: '{% data variables.product.prodname_copilot_chat_short %} can suggest ways to speed up slow-running code.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/refactoring-for-performance-optimization
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Simple
octicon: rocket
topics:
- Copilot
---
Existing code may function correctly but be inefficient, leading to performance bottlenecks. Examples of coding that can adversely impact performance include inefficient loops, unnecessary computations, and excessive memory allocation.
{% data variables.product.prodname_copilot_chat_short %} can identify performance hotspots and suggest refactoring strategies such as optimizing data structures (for example, using hashmaps instead of arrays), reducing redundant calculations, and improving algorithmic efficiency. It can also recommend caching mechanisms or parallelizing operations to improve performance.
## Example scenario
The following Python code prints every 1000th prime number up to the 10,000th prime. It includes a timer, and prints how long the code takes to run as the last line of the output. The program takes several seconds to complete.
```python
import time
def is_prime(n):
if n <= 1:
return False
for i in range(2, n):
if n % i == 0:
return False
return True
def every_1000th_prime():
primes = []
num = 2
while len(primes) < 10000:
if is_prime(num):
primes.append(num)
num += 1
return [primes[i] for i in range(999, 10000, 1000)]
if __name__ == "__main__":
start_time = time.time()
primes = every_1000th_prime()
for prime in primes:
print(prime)
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Time taken: {elapsed_time:.10f} seconds")
```
## Example prompt
`Optimize this code for performance`
## Example response
{% data variables.product.prodname_copilot_short %} suggests using a sieve function to generate the prime numbers much more efficiently. If you run this program it will complete in a fraction of a second.
> [!NOTE] {% data variables.product.prodname_copilot_chat_short %} responses are non-deterministic, so you may get a different response from the one shown here.
```python
import time
def sieve_of_eratosthenes(limit):
sieve = [True] * (limit + 1)
sieve[0] = sieve[1] = False
for start in range(2, int(limit**0.5) + 1):
if sieve[start]:
for multiple in range(start*start, limit + 1, start):
sieve[multiple] = False
return [num for num, is_prime in enumerate(sieve) if is_prime]
def every_1000th_prime():
limit = 105000 # Higher than needed to ensure 10,000 primes
primes = sieve_of_eratosthenes(limit)
return [primes[i] for i in range(999, 10000, 1000)]
if __name__ == "__main__":
start_time = time.time()
primes = every_1000th_prime()
for prime in primes:
print(prime)
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Time taken: {elapsed_time:.10f} seconds")
```
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,117 @@
---
title: Refactoring to implement a design pattern
shortTitle: Design patterns
intro: '{% data variables.product.prodname_copilot_chat_short %} can suggest design patterns that you can use to improve your code.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/refactoring-to-implement-a-design-pattern
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Intermediate
octicon: rocket
topics:
- Copilot
---
Code that doesnt follow established design patterns (like Singleton, Factory, or Observer) can lead to issues like tight coupling, lack of flexibility, or duplicated code.
{% data variables.product.prodname_copilot_chat_short %} can help you use appropriate design patterns to make your code more flexible and maintainable. For example, it can recommend converting repetitive instantiations into a Factory pattern, or using the Observer pattern to decouple tightly connected classes.
> [!NOTE] The responses described in this article are examples. {% data variables.product.prodname_copilot_chat_short %} responses are non-deterministic, so you may get different responses from the ones shown here.
## Example scenario
This JavaScript code creates three `Person` objects, each with `name` and `age` properties. It then uses the name of a person to retrieve and print their age.
```javascript
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
var people = {};
function addPerson(name, age) {
people[name] = new Person(name, age);
}
function getAge(name) {
if (people[name]) {
console.log(name + " is " + people[name].age + " years old.");
} else {
console.log("Person not found.");
}
}
addPerson("Ana", 30);
addPerson("Mario", 25);
addPerson("Louise", 40);
getAge("Mario");
```
## Example prompt 1
`What design patterns could improve this code? Don't show me code examples.`
## Example response 1
{% data variables.product.prodname_copilot_short %} suggests the following patterns:
* **Singleton pattern:** to ensure that there is only one instance of the `people` object.
* **Factory pattern:** to create a factory for creating `Person` objects.
* **Module pattern:** to encapsulate the `people` object and related functions within a module to avoid polluting the global namespace.
## Example prompt 2
You can now ask {% data variables.product.prodname_copilot_short %} to implement the pattern that you feel is most appropriate.
`Refactor this code using the module pattern`
## Example response 2
```javascript
const PersonModule = (function() {
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const people = {};
function addPerson(name, age) {
people[name] = new Person(name, age);
}
function getAge(name) {
if (people[name]) {
console.log(name + " is " + people[name].age + " years old.");
} else {
console.log("Person not found.");
}
}
return {
addPerson,
getAge
};
})();
PersonModule.addPerson("Ana", 30);
PersonModule.addPerson("Mario", 25);
PersonModule.addPerson("Louise", 40);
PersonModule.getAge("Mario");
```
The module pattern improves code organization, enhances data privacy, and reduces the risk of naming conflicts, making the code more maintainable and scalable.
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}

View File

@@ -0,0 +1,118 @@
---
title: Simplifying complex inheritance hierarchies
shortTitle: Simplify inheritance hierarchies
intro: '{% data variables.product.prodname_copilot_chat_short %} can help you to refactor code to avoid classes with multiple layers of inheritance.'
redirect_from:
- /copilot/example-prompts-for-github-copilot-chat/refactoring-code/simplifying-complex-inheritance-hierarchies
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Intermediate
octicon: rocket
topics:
- Copilot
---
Deep inheritance hierarchies, or improper use of inheritance, can lead to code that is hard to maintain, making it difficult to follow relationships between classes, or to extend them without causing breakage.
{% data variables.product.prodname_copilot_chat_short %} can suggest refactoring inheritance-based designs into more flexible composition-based designs (favoring composition over inheritance). It can also recommend applying patterns like Strategy or Decorator to make the system more extensible without adding complexity to the inheritance structure.
## Example scenario
The following C# code has a deep inheritance hierarchy where each class builds on the previous one. The result is a long chain of inheritance that makes it difficult to know what properties each class has.
A multi-level inheritance hierarchy like this can be difficult to understand, modify, and extend.
```csharp
public class Employee
{
public string Name { get; set; }
public int EmployeeID { get; set; }
}
public class Manager : Employee
{
public int NumberOfTeams { get; set; }
}
public class SeniorManager : Manager
{
public string Region { get; set; }
}
public class Director : SeniorManager
{
public int NumberOfDepartments { get; set; }
}
public class VicePresident : Director
{
public string Division { get; set; }
}
public class President : VicePresident
{
public string Company { get; set; }
}
```
## Example prompt
In this situation you might decide to use a parent `Employee` class whose properties other classes should inherit, but to avoid any other inheritance by defining all other properties separately for each class.
`Refactor this code so that classes only inherit the properties of the Employee class. All of the other properties that each class currently inherits should instead be declared independently in each class definition.`
## Example response
{% data reusables.copilot.example-prompts.response-is-an-example %}
{% data variables.product.prodname_copilot_short %} suggests the following code:
```csharp
public class Employee
{
public string Name { get; set; }
public int EmployeeID { get; set; }
}
public class Manager : Employee
{
public int NumberOfTeams { get; set; }
}
public class SeniorManager : Employee
{
public int NumberOfTeams { get; set; }
public string Region { get; set; }
}
public class Director : Employee
{
public int NumberOfTeams { get; set; }
public string Region { get; set; }
public int NumberOfDepartments { get; set; }
}
public class VicePresident : Employee
{
public int NumberOfTeams { get; set; }
public string Region { get; set; }
public int NumberOfDepartments { get; set; }
public string Division { get; set; }
}
public class President : Employee
{
public int NumberOfTeams { get; set; }
public string Region { get; set; }
public int NumberOfDepartments { get; set; }
public string Division { get; set; }
public string Company { get; set; }
}
```
## Further reading
{% data reusables.copilot.example-prompts.further-reading-items %}