Skip to content

Commit

Permalink
Merge branch 'master' into translation-to-Chinese
Browse files Browse the repository at this point in the history
  • Loading branch information
jnniu-n authored Oct 16, 2023
2 parents b12150b + f63c5dd commit 13e0a1b
Show file tree
Hide file tree
Showing 38 changed files with 528 additions and 49 deletions.
54 changes: 54 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -2670,6 +2670,60 @@
"contributions": [
"doc"
]
},
{
"login": "mribeirodantas",
"name": "Marcel Ribeiro-Dantas",
"avatar_url": "https://avatars.githubusercontent.com/u/1023197?v=4",
"profile": "http://mribeirodantas.me",
"contributions": [
"doc"
]
},
{
"login": "hamexhanif",
"name": "Muhammad Hanif Amrullah",
"avatar_url": "https://avatars.githubusercontent.com/u/74542852?v=4",
"profile": "https://github.com/hamexhanif",
"contributions": [
"translation"
]
},
{
"login": "JackH408",
"name": "JackH408",
"avatar_url": "https://avatars.githubusercontent.com/u/141727294?v=4",
"profile": "https://github.com/JackH408",
"contributions": [
"doc"
]
},
{
"login": "versus2004",
"name": "Shubham",
"avatar_url": "https://avatars.githubusercontent.com/u/132815243?v=4",
"profile": "https://github.com/versus2004",
"contributions": [
"translation"
]
},
{
"login": "inishantjain",
"name": "Nishant Jain",
"avatar_url": "https://avatars.githubusercontent.com/u/121454072?v=4",
"profile": "https://github.com/inishantjain",
"contributions": [
"doc"
]
},
{
"login": "hallowshaw",
"name": "Rhitam Chaudhury",
"avatar_url": "https://avatars.githubusercontent.com/u/90751158?v=4",
"profile": "https://github.com/hallowshaw",
"contributions": [
"doc"
]
}
],
"contributorsPerLine": 7,
Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- the line below needs to be an empty line C: (its because kramdown isnt
<!-- the line below needs to be an empty line C: (its because kramdown isn't
that smart and dearly wants an empty line before a heading to be able to
display it as such, e.g. website) -->

Expand All @@ -10,7 +10,7 @@
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-293-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-299-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

<br/>
Expand Down Expand Up @@ -451,6 +451,14 @@ This project is licensed under the terms of the MIT license.
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Upendra-Allagadda"><img src="https://avatars.githubusercontent.com/u/25962010?v=4?s=100" width="100px;" alt="Allagadda Sai Upendranath"/><br /><sub><b>Allagadda Sai Upendranath</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Upendra-Allagadda" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/mobraga/"><img src="https://avatars.githubusercontent.com/u/31048764?v=4?s=100" width="100px;" alt="Matheus Braga"/><br /><sub><b>Matheus Braga</b></sub></a><br /><a href="#translation-mathbraga" title="Translation">🌍</a> <a href="https://github.com/iluwatar/java-design-patterns/commits?author=mathbraga" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/satyabarghav"><img src="https://avatars.githubusercontent.com/u/36763910?v=4?s=100" width="100px;" alt="Appari Satya Barghav"/><br /><sub><b>Appari Satya Barghav</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=satyabarghav" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://mribeirodantas.me"><img src="https://avatars.githubusercontent.com/u/1023197?v=4?s=100" width="100px;" alt="Marcel Ribeiro-Dantas"/><br /><sub><b>Marcel Ribeiro-Dantas</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mribeirodantas" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hamexhanif"><img src="https://avatars.githubusercontent.com/u/74542852?v=4?s=100" width="100px;" alt="Muhammad Hanif Amrullah"/><br /><sub><b>Muhammad Hanif Amrullah</b></sub></a><br /><a href="#translation-hamexhanif" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JackH408"><img src="https://avatars.githubusercontent.com/u/141727294?v=4?s=100" width="100px;" alt="JackH408"/><br /><sub><b>JackH408</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=JackH408" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/versus2004"><img src="https://avatars.githubusercontent.com/u/132815243?v=4?s=100" width="100px;" alt="Shubham"/><br /><sub><b>Shubham</b></sub></a><br /><a href="#translation-versus2004" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/inishantjain"><img src="https://avatars.githubusercontent.com/u/121454072?v=4?s=100" width="100px;" alt="Nishant Jain"/><br /><sub><b>Nishant Jain</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=inishantjain" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hallowshaw"><img src="https://avatars.githubusercontent.com/u/90751158?v=4?s=100" width="100px;" alt="Rhitam Chaudhury"/><br /><sub><b>Rhitam Chaudhury</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=hallowshaw" title="Documentation">📖</a></td>
</tr>
</tbody>
</table>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
public class InformationController {

/**
* Endpoint to retrieve a product's informations.
* Endpoint to retrieve a product's information.
*
* @return product inventory.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
package com.iluwatar.caching.database;

/**
* Creates the database connection accroding the input parameter.
* Creates the database connection according the input parameter.
*/
public final class DbManagerFactory {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
/**
* <p>
* The intention of the Circuit Builder pattern is to handle remote failures robustly, which is to
* mean that if a service is dependant on n number of other services, and m of them fail, we should
* mean that if a service is dependent on n number of other services, and m of them fail, we should
* be able to recover from that failure by ensuring that the user can still use the services that
* are actually functional, and resources are not tied up by uselessly by the services which are not
* working. However, we should also be able to detect when any of the m failing services become
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public String call() throws RemoteServiceException {
}
};
var circuitBreaker = new DefaultCircuitBreaker(mockService, 1, 1, 100);
//Call with the paramater start_time set to huge amount of time in past so that service
//Call with the parameter start_time set to huge amount of time in past so that service
//replies with "Ok". Also, state is CLOSED in start
var serviceStartTime = System.nanoTime() - 60 * 1000 * 1000 * 1000;
var response = circuitBreaker.attemptRequest();
Expand Down
2 changes: 1 addition & 1 deletion commander/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This pattern can be used when we need to make commits into 2 (or more) databases

## Explanation
Handling distributed transactions can be tricky, but if we choose to not handle it carefully, there could be unwanted consequences. Say, we have an e-commerce website which has a Payment microservice and a Shipping microservice. If the shipping is available currently but payment service is not up, or vice versa, how would we deal with it after having already received the order from the user?
We need a mechanism in place which can handle these kinds of situations. We have to direct the order to either one of the services (in this example, shipping) and then add the order into the database of the other service (in this example, payment), since two databses cannot be updated atomically. If currently unable to do it, there should be a queue where this request can be queued, and there has to be a mechanism which allows for a failure in the queueing as well. All this needs to be done by constant retries while ensuring idempotence (even if the request is made several times, the change should only be applied once) by a commander class, to reach a state of eventual consistency.
We need a mechanism in place which can handle these kinds of situations. We have to direct the order to either one of the services (in this example, shipping) and then add the order into the database of the other service (in this example, payment), since two databases cannot be updated atomically. If currently unable to do it, there should be a queue where this request can be queued, and there has to be a mechanism which allows for a failure in the queueing as well. All this needs to be done by constant retries while ensuring idempotence (even if the request is made several times, the change should only be applied once) by a commander class, to reach a state of eventual consistency.

## Credits

Expand Down
2 changes: 1 addition & 1 deletion currying/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ Cons
* As shown in the programmatic example above, curried functions with several parameters have a cumbersome type signature (in Java).

## Related patterns
* [Builder patter](https://java-design-patterns.com/patterns/builder/)
* [Builder pattern](https://java-design-patterns.com/patterns/builder/)

## Credits
* [Currying in Java](https://www.baeldung.com/java-currying)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
package com.iluwatar.datamapper;

/**
* Using Runtime Exception for avoiding dependancy on implementation exceptions. This helps in
* Using Runtime Exception for avoiding dependency on implementation exceptions. This helps in
* decoupling.
*
* @author amit.dixit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static void main(String[] args) throws Exception {

// Create table for orders - Orders(id, name, orderedBy, city, state, pincode).
// We can see that table is different from the Order object we have.
// We're mapping ShippingAddress into city, state, pincode colummns of the database and not creating a separate table.
// We're mapping ShippingAddress into city, state, pincode columns of the database and not creating a separate table.
if (dataSource.createSchema()) {
LOGGER.info("TABLE CREATED");
LOGGER.info("Table \"Orders\" schema:\n" + dataSource.getSchema());
Expand Down Expand Up @@ -95,7 +95,7 @@ public static void main(String[] args) throws Exception {
dataSource.removeOrder(1);
LOGGER.info("\nOrders Query: {}", dataSource.queryOrders().collect(Collectors.toList()) + "\n");

//After successfull demonstration of the pattern, drop the table
//After successful demonstration of the pattern, drop the table
if (dataSource.deleteSchema()) {
LOGGER.info("TABLE DROPPED");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ private void update() {
clip.open(audioStream);
clip.start();
} catch (LineUnavailableException e) {
LOGGER.trace("Error occoured while loading the audio: The line is unavailable", e);
LOGGER.trace("Error occurred while loading the audio: The line is unavailable", e);
} catch (IOException e) {
LOGGER.trace("Input/Output error while loading the audio", e);
} catch (IllegalArgumentException e) {
Expand Down
2 changes: 1 addition & 1 deletion fanout-fanin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ service has received the requests. Now the caller will not wait or expect the re

Meanwhile, the pattern service will invoke the requests that have come. The requests might complete at different time.
These requests will be processed in different instances of the same function in different machines or services. As the
requests get completed, a callback service everytime is called that transforms the result into a common single object format
requests get completed, a callback service every time is called that transforms the result into a common single object format
that gets pushed to a consumer. The caller will be at the other end of the consumer receiving the result.

**Programmatic Example**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@


/**
* Consumer or callback class that will be called everytime a request is complete This will
* Consumer or callback class that will be called every time a request is complete This will
* aggregate individual result to form a final result.
*/
@Getter
Expand Down
64 changes: 60 additions & 4 deletions feature-toggle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,53 @@ tag:
Feature Flag

## Intent
Used to switch code execution paths based on properties or groupings. Allowing new features to be released, tested
and rolled out. Allowing switching back to the older feature quickly if needed. It should be noted that this pattern,
can easily introduce code complexity. There is also cause for concern that the old feature that the toggle is eventually
going to phase out is never removed, causing redundant code smells and increased maintainability.
A technique used in software development to control and manage the rollout of specific features or functionality in a
program without changing the code. It can act as an on/off switch for features depending on the status or properties of
other values in the program. This is similar to A/B testing, where features are rolled out based on properties such as
location or device. Implementing this design pattern can increase code complexity, and it is important to remember to
remove redundant code if this design pattern is being used to phase out a system or feature.

## Explanation
Real-world Example
> This design pattern works really well in any sort of development, in particular mobile development. Say you want to
> introduce a feature such as dark mode, but you want to ensure that the feature works correctly and don't want to roll
> out the feature to everyone immediately. You write in the code, and have it switched off as default. From here, it is
> easy to turn on the code for specific users based on selection criteria, or randomly. This will also allow the feature
> to be turned off easily without any drastic changes to the code, or any need for redeployment or updates.
In plain words
> Feature Toggle is a way to introduce new features gradually instead of deployment all at once.
Wikipedia says
> A feature toggle in software development provides an alternative to maintaining multiple feature branches in source
> code. A condition within the code enables or disables a feature during runtime. In agile settings the toggle is
> used in production, to switch on the feature on demand, for some or all the users.
## Programmatic Example
This example shows Java code that allows a feature to show when it is enabled by the developer, and when a user is a
Premium member of the application. This is useful for subscription locked features.
```java
public class FeatureToggleExample {
// Bool for feature enabled or disabled
private static boolean isNewFeatureEnabled = false;

public static void main(String[] args) {
boolean userIsPremium = true; // Example: Check if the user is a premium user

// Check if the new feature should be enabled for the user
if (userIsPremium && isNewFeatureEnabled) {
// User is premium and the new feature is enabled
showNewFeature();
}
}

private static void showNewFeature() {
// If user is allowed to see locked feature, this is where the code would go
}
}
```
The code shows how simple it is to implement this design pattern, and the criteria can be further refined or broadened
should the developers choose to do so.

## Class diagram
![alt text](./etc/feature-toggle.png "Feature Toggle")
Expand All @@ -24,7 +67,20 @@ Use the Feature Toggle pattern when
* Giving different features to different users.
* Rolling out a new feature incrementally.
* Switching between development and production environments.
* Quickly disable problematic features
* External management of feature deployment
* Ability to maintain multiple version releases of a feature
* 'Hidden' deployment, releasing a feature in code for designated testing but not publicly making it available

## Consequences
Consequences involved with using the Feature Toggle pattern

* Code complexity is increased
* Testing of multiple states is harder and more time-consuming
* Confusion between friends on why features are missing
* Keeping documentation up to date with all features can be difficult

## Credits

* [Martin Fowler 29 October 2010 (2010-10-29).](http://martinfowler.com/bliki/FeatureToggle.html)
* [Feature Toggle - Java Design Patterns](https://java-design-patterns.com/patterns/feature-toggle/)
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
* version of the feature toggle, where the enhanced version of the welcome message which is
* personalised is turned either on or off at instance creation. This method is not as dynamic as
* the {@link User} driven version where the feature of the personalised welcome message is
* dependant on the {@link UserGroup} the {@link User} is in. So if the user is a memeber of the
* {@link UserGroup#isPaid(User)} then they get an ehanced version of the welcome message.
* dependent on the {@link UserGroup} the {@link User} is in. So if the user is a member of the
* {@link UserGroup#isPaid(User)} then they get an enhanced version of the welcome message.
*
* <p>Note that this pattern can easily introduce code complexity, and if not kept in check can
* result in redundant unmaintained code within the codebase.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import lombok.Getter;

/**
* This example of the Feature Toogle pattern is less dynamic version than {@link
* This example of the Feature Toggle pattern is less dynamic version than {@link
* com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} where the feature is
* turned on or off at the time of creation of the service. This example uses simple Java {@link
* Properties} however it could as easily be done with an external configuration file loaded by
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import com.iluwatar.featuretoggle.user.UserGroup;

/**
* This example of the Feature Toogle pattern shows how it could be implemented based on a {@link
* This example of the Feature Toggle pattern shows how it could be implemented based on a {@link
* User}. Therefore showing its use within a tiered application where the paying users get access to
* different content or better versions of features. So in this instance a {@link User} is passed in
* and if they are found to be on the {@link UserGroup#isPaid(User)} they are welcomed with a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public abstract class AbstractMessageManager implements MessageManager {
protected Map<Integer, Instance> instanceMap;

/**
* Construtor of AbstractMessageManager.
* Constructor of AbstractMessageManager.
*/
public AbstractMessageManager(Map<Integer, Instance> instanceMap) {
this.instanceMap = instanceMap;
Expand Down
Loading

0 comments on commit 13e0a1b

Please sign in to comment.