From 6fe219d644bb9f80c4190c82b1a45eb91089bc88 Mon Sep 17 00:00:00 2001 From: ZhouSky <57678580+ZhouSky@users.noreply.github.com> Date: Sat, 4 Jul 2020 17:05:46 +0800 Subject: [PATCH] Pr/1235 Review (#1250) * Add simple implementation for strangler pattern. * Add strangler pattern in pom.xml. * change package name * Revert "change package name" This reverts commit 430bd9073ea7bea6430586a0953c77f1798aacc8. * Code review for strangler Delete final of method parameters. Add final to private members. Change package name. * Revert "Code review for strangler" This reverts commit d5063567083e0348d678a938bd749e17343bcb8e. * Revert "Revert "Code review for strangler"" This reverts commit c8fd65fda782749c4f74f6de85da0f271d3c48a8. * Remove unnecessary files --- pom.xml | 1 + strangler/README.md | 31 ++++++++ strangler/etc/strangler.png | Bin 0 -> 77937 bytes strangler/etc/strangler.puml | 61 +++++++++++++++ strangler/pom.xml | 66 ++++++++++++++++ .../main/java/com/iluwatar/strangler/App.java | 69 ++++++++++++++++ .../iluwatar/strangler/HalfArithmetic.java | 74 ++++++++++++++++++ .../com/iluwatar/strangler/HalfSource.java | 54 +++++++++++++ .../com/iluwatar/strangler/NewArithmetic.java | 71 +++++++++++++++++ .../com/iluwatar/strangler/NewSource.java | 56 +++++++++++++ .../com/iluwatar/strangler/OldArithmetic.java | 61 +++++++++++++++ .../com/iluwatar/strangler/OldSource.java | 59 ++++++++++++++ .../java/com/iluwatar/strangler/AppTest.java | 36 +++++++++ .../strangler/HalfArithmeticTest.java | 50 ++++++++++++ .../iluwatar/strangler/HalfSourceTest.java | 47 +++++++++++ .../iluwatar/strangler/NewArithmeticTest.java | 50 ++++++++++++ .../com/iluwatar/strangler/NewSourceTest.java | 51 ++++++++++++ .../iluwatar/strangler/OldArithmeticTest.java | 45 +++++++++++ .../com/iluwatar/strangler/OldSourceTest.java | 45 +++++++++++ 19 files changed, 927 insertions(+) create mode 100644 strangler/README.md create mode 100644 strangler/etc/strangler.png create mode 100644 strangler/etc/strangler.puml create mode 100644 strangler/pom.xml create mode 100644 strangler/src/main/java/com/iluwatar/strangler/App.java create mode 100644 strangler/src/main/java/com/iluwatar/strangler/HalfArithmetic.java create mode 100644 strangler/src/main/java/com/iluwatar/strangler/HalfSource.java create mode 100644 strangler/src/main/java/com/iluwatar/strangler/NewArithmetic.java create mode 100644 strangler/src/main/java/com/iluwatar/strangler/NewSource.java create mode 100644 strangler/src/main/java/com/iluwatar/strangler/OldArithmetic.java create mode 100644 strangler/src/main/java/com/iluwatar/strangler/OldSource.java create mode 100644 strangler/src/test/java/com/iluwatar/strangler/AppTest.java create mode 100644 strangler/src/test/java/com/iluwatar/strangler/HalfArithmeticTest.java create mode 100644 strangler/src/test/java/com/iluwatar/strangler/HalfSourceTest.java create mode 100644 strangler/src/test/java/com/iluwatar/strangler/NewArithmeticTest.java create mode 100644 strangler/src/test/java/com/iluwatar/strangler/NewSourceTest.java create mode 100644 strangler/src/test/java/com/iluwatar/strangler/OldArithmeticTest.java create mode 100644 strangler/src/test/java/com/iluwatar/strangler/OldSourceTest.java diff --git a/pom.xml b/pom.xml index 93e0fc03b..f23369107 100644 --- a/pom.xml +++ b/pom.xml @@ -190,6 +190,7 @@ combinator update-method leader-followers + strangler arrange-act-assert diff --git a/strangler/README.md b/strangler/README.md new file mode 100644 index 000000000..2f157f1d2 --- /dev/null +++ b/strangler/README.md @@ -0,0 +1,31 @@ +--- +layout: pattern +title: Strangler +folder: strangler +permalink: /patterns/strangler/ +categories: Structural +tags: + - Extensibility +--- + +## Intent +Incrementally migrate a legacy system by gradually replacing specific pieces of functionality +with new applications and services. As features from the legacy system are replaced, the new +system eventually covers all the old system's features and may has its own new features, then +strangling the old system and allowing you to decommission it. + +## Class diagram +![alt text](./etc/strangler.png "Strangler") + +## Applicability +This strangler pattern is a safe way to phase one thing out for something better, cheaper, or +more expandable. Especially when you want to update legacy system with new techniques and need +continuously develop new features at the same time. Note that this pattern indeed need extra effort, +so usually use it when the system is not so simple. + +## Credits + +* [Strangler pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/strangler#context-and-problem) +* [Legacy Application Strangulation : Case Studies](https://paulhammant.com/2013/07/14/legacy-application-strangulation-case-studies/) + + diff --git a/strangler/etc/strangler.png b/strangler/etc/strangler.png new file mode 100644 index 0000000000000000000000000000000000000000..c69305e5d510465a75b001096cdd7c8c15631ed5 GIT binary patch literal 77937 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

#F}1lmPB;v?LX5AgNsNa&jF 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 literal 0 HcmV?d00001 diff --git a/strangler/etc/strangler.puml b/strangler/etc/strangler.puml new file mode 100644 index 000000000..cb2c266a1 --- /dev/null +++ b/strangler/etc/strangler.puml @@ -0,0 +1,61 @@ +@startuml + +package com.iluwatar.strangler { + class App { + + main(args : String[]) {static} + } + + class OldArithmetic { + - LOGGER : Logger {static} + - VERSION : String {static} + - source : OldSource + + sum(nums : int...) + + mul(nums : int...) + } + + class HalfArithmetic { + - LOGGER : Logger {static} + - VERSION : String {static} + - oldSource : OldSource + - newSource : HalfSource + + sum(nums : int...) + + mul(nums : int...) + + ifHasZero(nums : int...) + } + + class NewArithmetic { + - LOGGER : Logger {static} + - VERSION : String {static} + - source : NewSource + + sum(nums : int...) + + mul(nums : int...) + + ifHasZero(nums : int...) + } + + class OldSource { + - LOGGER : Logger {static} + - VERSION : String {static} + + accumulateSum(nums : int...) + + accumulateMul(nums : int...) + } + + class HalfSource { + - LOGGER : Logger {static} + - VERSION : String {static} + + accumulateSum(nums : int...) + + ifNonZero(nums : int...) + } + + class NewSource { + - LOGGER : Logger {static} + - VERSION : String {static} + + accumulateSum(nums : int...) + + accumulateMul(nums : int...) + + ifNonZero(nums : int...) + } +} +OldArithmetic o--> OldSource +HalfArithmetic o--> OldSource +HalfArithmetic o--> HalfSource +NewArithmetic o--> NewSource +@enduml \ No newline at end of file diff --git a/strangler/pom.xml b/strangler/pom.xml new file mode 100644 index 000000000..4a1fb42ba --- /dev/null +++ b/strangler/pom.xml @@ -0,0 +1,66 @@ + + + + + java-design-patterns + com.iluwatar + 1.23.0-SNAPSHOT + + 4.0.0 + + strangler + + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.strangler.App + + + + + + + + + + + \ No newline at end of file diff --git a/strangler/src/main/java/com/iluwatar/strangler/App.java b/strangler/src/main/java/com/iluwatar/strangler/App.java new file mode 100644 index 000000000..bba0f7f74 --- /dev/null +++ b/strangler/src/main/java/com/iluwatar/strangler/App.java @@ -0,0 +1,69 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +/** + * + *

The Strangler pattern is a software design pattern that incrementally migrate a legacy + * system by gradually replacing specific pieces of functionality with new applications and + * services. As features from the legacy system are replaced, the new system eventually + * replaces all of the old system's features, strangling the old system and allowing you + * to decommission it.

+ * + *

This pattern is not only about updating but also enhancement.

+ * + *

In this example, {@link OldArithmetic} indicates old system and its implementation depends + * on its source ({@link OldSource}). Now we tend to update system with new techniques and + * new features. In reality, the system may too complex, so usually need gradual migration. + * {@link HalfArithmetic} indicates system in the process of migration, its implementation + * depends on old one ({@link OldSource}) and under development one ({@link HalfSource}). The + * {@link HalfSource} covers part of {@link OldSource} and add new functionality. You can release + * this version system with new features, which also supports old version system functionalities. + * After whole migration, the new system ({@link NewArithmetic}) only depends on new source + * ({@link NewSource}).

+ * + */ +public class App { + /** + * Program entry point. + * @param args command line args + */ + public static void main(final String[] args) { + final var nums = new int[]{1, 2, 3, 4, 5}; + //Before migration + final var oldSystem = new OldArithmetic(new OldSource()); + oldSystem.sum(nums); + oldSystem.mul(nums); + //In process of migration + final var halfSystem = new HalfArithmetic(new HalfSource(), new OldSource()); + halfSystem.sum(nums); + halfSystem.mul(nums); + halfSystem.ifHasZero(nums); + //After migration + final var newSystem = new NewArithmetic(new NewSource()); + newSystem.sum(nums); + newSystem.mul(nums); + newSystem.ifHasZero(nums); + } +} diff --git a/strangler/src/main/java/com/iluwatar/strangler/HalfArithmetic.java b/strangler/src/main/java/com/iluwatar/strangler/HalfArithmetic.java new file mode 100644 index 000000000..be9c15ec5 --- /dev/null +++ b/strangler/src/main/java/com/iluwatar/strangler/HalfArithmetic.java @@ -0,0 +1,74 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * System under migration. Depends on old version source ({@link OldSource}) and + * developing one ({@link HalfSource}). + */ +public class HalfArithmetic { + private static final Logger LOGGER = LoggerFactory.getLogger(HalfArithmetic.class); + private static final String VERSION = "1.5"; + + private final HalfSource newSource; + private final OldSource oldSource; + + public HalfArithmetic(HalfSource newSource, OldSource oldSource) { + this.newSource = newSource; + this.oldSource = oldSource; + } + + /** + * Accumulate sum. + * @param nums numbers need to add together + * @return accumulate sum + */ + public int sum(int... nums) { + LOGGER.info("Arithmetic sum {}", VERSION); + return newSource.accumulateSum(nums); + } + + /** + * Accumulate multiplication. + * @param nums numbers need to multiply together + * @return accumulate multiplication + */ + public int mul(int... nums) { + LOGGER.info("Arithmetic mul {}", VERSION); + return oldSource.accumulateMul(nums); + } + + /** + * Chech if has any zero. + * @param nums numbers need to check + * @return if has any zero, return true, else, return false + */ + public boolean ifHasZero(int... nums) { + LOGGER.info("Arithmetic check zero {}", VERSION); + return !newSource.ifNonZero(nums); + } +} diff --git a/strangler/src/main/java/com/iluwatar/strangler/HalfSource.java b/strangler/src/main/java/com/iluwatar/strangler/HalfSource.java new file mode 100644 index 000000000..b83293335 --- /dev/null +++ b/strangler/src/main/java/com/iluwatar/strangler/HalfSource.java @@ -0,0 +1,54 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Source under development. Replace part of old source and has added some new features. + */ +public class HalfSource { + private static final Logger LOGGER = LoggerFactory.getLogger(HalfSource.class); + private static final String VERSION = "1.5"; + + /** + * Implement accumulate sum with new technique. + * Replace old one in {@link OldSource} + */ + public int accumulateSum(int... nums) { + LOGGER.info("Source module {}", VERSION); + return Arrays.stream(nums).reduce(0, Integer::sum); + } + + /** + * Check if all number is not zero. + * New feature. + */ + public boolean ifNonZero(int... nums) { + LOGGER.info("Source module {}", VERSION); + return Arrays.stream(nums).allMatch(num -> num != 0); + } +} diff --git a/strangler/src/main/java/com/iluwatar/strangler/NewArithmetic.java b/strangler/src/main/java/com/iluwatar/strangler/NewArithmetic.java new file mode 100644 index 000000000..8e482c8b3 --- /dev/null +++ b/strangler/src/main/java/com/iluwatar/strangler/NewArithmetic.java @@ -0,0 +1,71 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * System after whole migration. Only depends on new version source ({@link NewSource}). + */ +public class NewArithmetic { + private static final Logger LOGGER = LoggerFactory.getLogger(NewArithmetic.class); + private static final String VERSION = "2.0"; + + private final NewSource source; + + public NewArithmetic(NewSource source) { + this.source = source; + } + + /** + * Accumulate sum. + * @param nums numbers need to add together + * @return accumulate sum + */ + public int sum(int... nums) { + LOGGER.info("Arithmetic sum {}", VERSION); + return source.accumulateSum(nums); + } + + /** + * Accumulate multiplication. + * @param nums numbers need to multiply together + * @return accumulate multiplication + */ + public int mul(int... nums) { + LOGGER.info("Arithmetic mul {}", VERSION); + return source.accumulateMul(nums); + } + + /** + * Chech if has any zero. + * @param nums numbers need to check + * @return if has any zero, return true, else, return false + */ + public boolean ifHasZero(int... nums) { + LOGGER.info("Arithmetic check zero {}", VERSION); + return !source.ifNonZero(nums); + } +} diff --git a/strangler/src/main/java/com/iluwatar/strangler/NewSource.java b/strangler/src/main/java/com/iluwatar/strangler/NewSource.java new file mode 100644 index 000000000..f53a31bd8 --- /dev/null +++ b/strangler/src/main/java/com/iluwatar/strangler/NewSource.java @@ -0,0 +1,56 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * New source. Completely covers functionalities of old source with new techniques + * and also has some new features. + */ +public class NewSource { + private static final Logger LOGGER = LoggerFactory.getLogger(NewSource.class); + private static final String VERSION = "2.0"; + + public int accumulateSum(int... nums) { + LOGGER.info("Source module {}", VERSION); + return Arrays.stream(nums).reduce(0, Integer::sum); + } + + /** + * Implement accumulate multiply with new technique. + * Replace old one in {@link OldSource} + */ + public int accumulateMul(int... nums) { + LOGGER.info("Source module {}", VERSION); + return Arrays.stream(nums).reduce(1, (a, b) -> a * b); + } + + public boolean ifNonZero(int... nums) { + LOGGER.info("Source module {}", VERSION); + return Arrays.stream(nums).allMatch(num -> num != 0); + } +} diff --git a/strangler/src/main/java/com/iluwatar/strangler/OldArithmetic.java b/strangler/src/main/java/com/iluwatar/strangler/OldArithmetic.java new file mode 100644 index 000000000..e9d57987a --- /dev/null +++ b/strangler/src/main/java/com/iluwatar/strangler/OldArithmetic.java @@ -0,0 +1,61 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Old version system depends on old version source ({@link OldSource}). + */ +public class OldArithmetic { + private static final Logger LOGGER = LoggerFactory.getLogger(OldArithmetic.class); + private static final String VERSION = "1.0"; + + private final OldSource source; + + public OldArithmetic(OldSource source) { + this.source = source; + } + + /** + * Accumulate sum. + * @param nums numbers need to add together + * @return accumulate sum + */ + public int sum(int... nums) { + LOGGER.info("Arithmetic sum {}", VERSION); + return source.accumulateSum(nums); + } + + /** + * Accumulate multiplication. + * @param nums numbers need to multiply together + * @return accumulate multiplication + */ + public int mul(int... nums) { + LOGGER.info("Arithmetic mul {}", VERSION); + return source.accumulateMul(nums); + } +} diff --git a/strangler/src/main/java/com/iluwatar/strangler/OldSource.java b/strangler/src/main/java/com/iluwatar/strangler/OldSource.java new file mode 100644 index 000000000..0ac0b5a07 --- /dev/null +++ b/strangler/src/main/java/com/iluwatar/strangler/OldSource.java @@ -0,0 +1,59 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Old source with techniques out of date. + */ +public class OldSource { + private static final Logger LOGGER = LoggerFactory.getLogger(OldSource.class); + private static final String VERSION = "1.0"; + + /** + * Implement accumulate sum with old technique. + */ + public int accumulateSum(int... nums) { + LOGGER.info("Source module {}", VERSION); + var sum = 0; + for (final var num : nums) { + sum += num; + } + return sum; + } + + /** + * Implement accumulate multiply with old technique. + */ + public int accumulateMul(int... nums) { + LOGGER.info("Source module {}", VERSION); + var sum = 1; + for (final var num : nums) { + sum *= num; + } + return sum; + } +} diff --git a/strangler/src/test/java/com/iluwatar/strangler/AppTest.java b/strangler/src/test/java/com/iluwatar/strangler/AppTest.java new file mode 100644 index 000000000..a9e878a94 --- /dev/null +++ b/strangler/src/test/java/com/iluwatar/strangler/AppTest.java @@ -0,0 +1,36 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.junit.jupiter.api.Test; + +/** + * Application test + */ +public class AppTest { + @Test + public void test() { + App.main(new String[]{}); + } +} diff --git a/strangler/src/test/java/com/iluwatar/strangler/HalfArithmeticTest.java b/strangler/src/test/java/com/iluwatar/strangler/HalfArithmeticTest.java new file mode 100644 index 000000000..004631966 --- /dev/null +++ b/strangler/src/test/java/com/iluwatar/strangler/HalfArithmeticTest.java @@ -0,0 +1,50 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test methods in HalfArithmetic + */ +class HalfArithmeticTest { + private static final HalfArithmetic arithmetic = new HalfArithmetic(new HalfSource(), new OldSource()); + + @Test + public void testSum() { + assertEquals(0, arithmetic.sum(-1, 0, 1)); + } + + @Test + public void testMul() { + assertEquals(0, arithmetic.mul(-1, 0, 1)); + } + + @Test + public void testIfHasZero() { + assertTrue(arithmetic.ifHasZero(-1, 0, 1)); + } +} \ No newline at end of file diff --git a/strangler/src/test/java/com/iluwatar/strangler/HalfSourceTest.java b/strangler/src/test/java/com/iluwatar/strangler/HalfSourceTest.java new file mode 100644 index 000000000..a8f9fc6ac --- /dev/null +++ b/strangler/src/test/java/com/iluwatar/strangler/HalfSourceTest.java @@ -0,0 +1,47 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Test methods in HalfSource + */ +public class HalfSourceTest { + private static final HalfSource source = new HalfSource(); + + @Test + public void testAccumulateSum() { + assertEquals(0, source.accumulateSum(-1, 0, 1)); + } + + @Test + public void testIfNonZero() { + assertFalse(source.ifNonZero(-1, 0, 1)); + } +} diff --git a/strangler/src/test/java/com/iluwatar/strangler/NewArithmeticTest.java b/strangler/src/test/java/com/iluwatar/strangler/NewArithmeticTest.java new file mode 100644 index 000000000..edb20241b --- /dev/null +++ b/strangler/src/test/java/com/iluwatar/strangler/NewArithmeticTest.java @@ -0,0 +1,50 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test methods in NewArithmetic + */ +class NewArithmeticTest { + private static final NewArithmetic arithmetic = new NewArithmetic(new NewSource()); + + @Test + public void testSum() { + assertEquals(0, arithmetic.sum(-1, 0, 1)); + } + + @Test + public void testMul() { + assertEquals(0, arithmetic.mul(-1, 0, 1)); + } + + @Test + public void testIfHasZero() { + assertTrue(arithmetic.ifHasZero(-1, 0, 1)); + } +} \ No newline at end of file diff --git a/strangler/src/test/java/com/iluwatar/strangler/NewSourceTest.java b/strangler/src/test/java/com/iluwatar/strangler/NewSourceTest.java new file mode 100644 index 000000000..577cc0daf --- /dev/null +++ b/strangler/src/test/java/com/iluwatar/strangler/NewSourceTest.java @@ -0,0 +1,51 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +/** + * Test methods in NewSource + */ +public class NewSourceTest { + private static final NewSource source = new NewSource(); + + @Test + public void testAccumulateSum() { + assertEquals(0, source.accumulateSum(-1, 0, 1)); + } + + @Test + public void testAccumulateMul() { + assertEquals(0, source.accumulateMul(-1, 0, 1)); + } + + @Test + public void testIfNonZero() { + assertFalse(source.ifNonZero(-1, 0, 1)); + } +} diff --git a/strangler/src/test/java/com/iluwatar/strangler/OldArithmeticTest.java b/strangler/src/test/java/com/iluwatar/strangler/OldArithmeticTest.java new file mode 100644 index 000000000..7f653d311 --- /dev/null +++ b/strangler/src/test/java/com/iluwatar/strangler/OldArithmeticTest.java @@ -0,0 +1,45 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test methods in OldArithmetic + */ +class OldArithmeticTest { + private static final OldArithmetic arithmetic = new OldArithmetic(new OldSource()); + + @Test + public void testSum() { + assertEquals(0, arithmetic.sum(-1, 0, 1)); + } + + @Test + public void testMul() { + assertEquals(0, arithmetic.mul(-1, 0, 1)); + } +} \ No newline at end of file diff --git a/strangler/src/test/java/com/iluwatar/strangler/OldSourceTest.java b/strangler/src/test/java/com/iluwatar/strangler/OldSourceTest.java new file mode 100644 index 000000000..12d6a6c14 --- /dev/null +++ b/strangler/src/test/java/com/iluwatar/strangler/OldSourceTest.java @@ -0,0 +1,45 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.strangler; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Test methods in OldSource + */ +public class OldSourceTest { + private static final OldSource source = new OldSource(); + + @Test + public void testAccumulateSum() { + assertEquals(0, source.accumulateSum(-1, 0, 1)); + } + + @Test + public void testAccumulateMul() { + assertEquals(0, source.accumulateMul(-1, 0, 1)); + } +}