├── .gitignore ├── README.md ├── maintainabilitybook.sln ├── pom.xml └── src ├── csharp ├── Properties │ └── AssemblyInfo.cs ├── eu │ └── sig │ │ └── training │ │ ├── ch02 │ │ ├── BalancesServlet.cs │ │ ├── BoardFactory.cs │ │ ├── Employees.cs │ │ ├── Level.cs │ │ ├── LevelHelper.cs │ │ ├── v1 │ │ │ └── BoardFactory.cs │ │ └── v2 │ │ │ └── BoardFactory.cs │ │ ├── ch03 │ │ ├── Flag.cs │ │ ├── FlagFactory.cs │ │ ├── FlagFactoryOops.cs │ │ ├── FlagFactoryWithMap.cs │ │ ├── JenkinsUser.cs │ │ ├── Nationality.cs │ │ ├── binarytree │ │ │ ├── BinaryTreeNode.cs │ │ │ ├── TreeException.cs │ │ │ ├── v1 │ │ │ │ └── BinaryTreeSearch.cs │ │ │ ├── v2 │ │ │ │ └── BinaryTreeSearch.cs │ │ │ └── v3 │ │ │ │ └── BinaryTreeSearch.cs │ │ └── withmapandtypes │ │ │ ├── BelgianFlag.cs │ │ │ ├── DefaultFlag.cs │ │ │ ├── DutchFlag.cs │ │ │ ├── FlagFactory.cs │ │ │ ├── FrenchFlag.cs │ │ │ ├── GermanFlag.cs │ │ │ ├── IFlag.cs │ │ │ └── ItalianFlag.cs │ │ ├── ch04 │ │ ├── BusinessException.cs │ │ ├── Clones.cs │ │ ├── Money.cs │ │ ├── v1 │ │ │ ├── Accounts.cs │ │ │ ├── CheckingAccount.cs │ │ │ ├── SavingsAccount.cs │ │ │ └── Transfer.cs │ │ ├── v2 │ │ │ ├── Accounts.cs │ │ │ ├── CheckingAccount.cs │ │ │ ├── SavingsAccount.cs │ │ │ └── Transfer.cs │ │ ├── v3 │ │ │ ├── Account.cs │ │ │ ├── Accounts.cs │ │ │ ├── CheckingAccount.cs │ │ │ ├── SavingsAccount.cs │ │ │ └── Transfer.cs │ │ └── v4 │ │ │ ├── Account.cs │ │ │ ├── Accounts.cs │ │ │ └── Transfer.cs │ │ ├── ch05 │ │ ├── boardpanel │ │ │ ├── v1 │ │ │ │ └── BoardPanel.cs │ │ │ ├── v2 │ │ │ │ ├── BoardPanel.cs │ │ │ │ └── Rectangle.cs │ │ │ └── v3 │ │ │ │ └── BoardPanel.cs │ │ ├── buildandsendmail │ │ │ ├── v1 │ │ │ │ └── BuildAndSendMail.cs │ │ │ └── v2 │ │ │ │ └── BuildAndSendMail.cs │ │ └── chartlib │ │ │ ├── v1 │ │ │ └── Charts.cs │ │ │ └── v2 │ │ │ └── BarChart.cs │ │ ├── ch06 │ │ ├── advanceddigitalcamera │ │ │ ├── DigitalCamera.cs │ │ │ └── Video.cs │ │ ├── digitalcamera │ │ │ ├── DigitalCamera.cs │ │ │ └── SmartphoneApp.cs │ │ ├── simpledigitalcamera │ │ │ ├── DigitalCamera.cs │ │ │ ├── ISimpleDigitalCamera.cs │ │ │ ├── SDK.cs │ │ │ └── SmartphoneApp.cs │ │ └── userservice │ │ │ ├── NotificationType.cs │ │ │ ├── User.cs │ │ │ ├── UserInfo.cs │ │ │ ├── splitted │ │ │ ├── UserBlockService.cs │ │ │ ├── UserNotificationService.cs │ │ │ └── UserService.cs │ │ │ ├── v1 │ │ │ ├── UserRestAPI.cs │ │ │ └── UserService.cs │ │ │ ├── v2 │ │ │ ├── NotificationRestAPI.cs │ │ │ └── UserService.cs │ │ │ └── v3 │ │ │ └── UserService.cs │ │ ├── ch07 │ │ ├── AWSCloudServerFactory.cs │ │ ├── AWSCloudStorage.cs │ │ ├── AWSComputeServer.cs │ │ ├── AWSDatabaseServer.cs │ │ ├── ApplicationLauncher.cs │ │ ├── AzureCloudServerFactory.cs │ │ ├── AzureCloudStorage.cs │ │ ├── AzureComputeServer.cs │ │ ├── AzureDatabaseServer.cs │ │ ├── ICloudServer.cs │ │ ├── ICloudServerFactory.cs │ │ └── ICloudStorage.cs │ │ ├── ch10 │ │ ├── PerfectPicture.cs │ │ └── Program.cs │ │ └── ch11 │ │ ├── DeadCode.cs │ │ ├── MagicConstants.cs │ │ └── StandardContext.cs ├── maintainabilitybook.csproj └── packages.config ├── java └── eu │ └── sig │ └── training │ ├── ch02 │ ├── BalancesServlet.java │ ├── BoardFactory.java │ ├── Employees.java │ ├── Level.java │ ├── LevelHelper.java │ ├── v1 │ │ └── BoardFactory.java │ └── v2 │ │ └── BoardFactory.java │ ├── ch03 │ ├── Flag.java │ ├── FlagFactory.java │ ├── FlagFactoryOops.java │ ├── FlagFactoryWithMap.java │ ├── JenkinsUser.java │ ├── Nationality.java │ ├── binarytree │ │ ├── BinaryTreeNode.java │ │ ├── TreeException.java │ │ ├── v1 │ │ │ └── BinaryTreeSearch.java │ │ ├── v2 │ │ │ └── BinaryTreeSearch.java │ │ └── v3 │ │ │ └── BinaryTreeSearch.java │ └── withmapandtypes │ │ ├── BelgianFlag.java │ │ ├── DefaultFlag.java │ │ ├── DutchFlag.java │ │ ├── Flag.java │ │ ├── FlagFactory.java │ │ ├── FrenchFlag.java │ │ ├── GermanFlag.java │ │ └── ItalianFlag.java │ ├── ch04 │ ├── BusinessException.java │ ├── Clones.java │ ├── Money.java │ ├── v1 │ │ ├── Accounts.java │ │ ├── CheckingAccount.java │ │ ├── SavingsAccount.java │ │ └── Transfer.java │ ├── v2 │ │ ├── Accounts.java │ │ ├── CheckingAccount.java │ │ ├── SavingsAccount.java │ │ └── Transfer.java │ ├── v3 │ │ ├── Account.java │ │ ├── Accounts.java │ │ ├── CheckingAccount.java │ │ ├── SavingsAccount.java │ │ └── Transfer.java │ └── v4 │ │ ├── Account.java │ │ ├── Accounts.java │ │ └── Transfer.java │ ├── ch05 │ ├── boardpanel │ │ ├── v1 │ │ │ └── BoardPanel.java │ │ ├── v2 │ │ │ ├── BoardPanel.java │ │ │ └── Rectangle.java │ │ └── v3 │ │ │ └── BoardPanel.java │ ├── buildandsendmail │ │ ├── v1 │ │ │ └── BuildAndSendMail.java │ │ └── v2 │ │ │ └── BuildAndSendMail.java │ └── chartlib │ │ ├── v1 │ │ └── Charts.java │ │ └── v2 │ │ └── BarChart.java │ ├── ch06 │ ├── advanceddigitalcamera │ │ ├── DigitalCamera.java │ │ └── Video.java │ ├── digitalcamera │ │ ├── DigitalCamera.java │ │ └── SmartphoneApp.java │ ├── simpledigitalcamera │ │ ├── DigitalCamera.java │ │ ├── SDK.java │ │ ├── SimpleDigitalCamera.java │ │ └── SmartphoneApp.java │ └── userservice │ │ ├── NotificationType.java │ │ ├── User.java │ │ ├── UserInfo.java │ │ ├── splitted │ │ ├── UserBlockService.java │ │ ├── UserNotificationService.java │ │ └── UserService.java │ │ ├── v1 │ │ ├── UserRestAPI.java │ │ └── UserService.java │ │ ├── v2 │ │ ├── NotificationRestAPI.java │ │ └── UserService.java │ │ └── v3 │ │ └── UserService.java │ ├── ch07 │ ├── AWSCloudServerFactory.java │ ├── AWSCloudStorage.java │ ├── AWSComputeServer.java │ ├── AWSDatabaseServer.java │ ├── ApplicationLauncher.java │ ├── AzureCloudServerFactory.java │ ├── AzureCloudStorage.java │ ├── AzureComputeServer.java │ ├── AzureDatabaseServer.java │ ├── CloudServer.java │ ├── CloudServerFactory.java │ └── CloudStorage.java │ ├── ch10 │ ├── PerfectPicture.java │ └── Program.java │ └── ch11 │ ├── DeadCode.java │ ├── MagicConstants.java │ ├── PluginManager.java │ ├── StandardContext.java │ └── ValuableVsNonValuableComments.java └── test ├── csharp ├── Properties │ └── AssemblyInfo.cs ├── eu │ └── sig │ │ └── training │ │ ├── ch03 │ │ ├── FlagFactoryWithMapTest.cs │ │ ├── FlagsTest.cs │ │ ├── binarytree │ │ │ └── BinaryTreeSearchTest.cs │ │ └── withmapandtypes │ │ │ └── FlagsTest.cs │ │ ├── ch04 │ │ ├── v1 │ │ │ └── AccountsTest.cs │ │ ├── v3 │ │ │ ├── CheckingAccountTest.cs │ │ │ └── SavingsAccountTest.cs │ │ └── v4 │ │ │ └── AccountsTest.cs │ │ ├── ch06 │ │ └── userservice │ │ │ ├── v1 │ │ │ └── UserControllerTest.cs │ │ │ └── v2 │ │ │ └── NotificationControllerTest.cs │ │ └── ch10 │ │ ├── PerfectPictureMockTest.cs │ │ └── PerfectPictureTest.cs ├── maintainabilitybooktests.csproj └── packages.config ├── java └── eu │ └── sig │ └── training │ ├── ch03 │ ├── FlagFactoryWithMapTest.java │ ├── FlagsTest.java │ └── binarytree │ │ └── BinaryTreeSearchTest.java │ ├── ch04 │ ├── v1 │ │ └── AccountsTest.java │ ├── v3 │ │ ├── CheckingAccountTest.java │ │ └── SavingsAccountTest.java │ └── v4 │ │ └── AccountsTest.java │ └── ch10 │ ├── PerfectPictureMockTest.java │ └── PerfectPictureTest.java └── resources ├── VanGoghStarryNight.jpg └── VanGoghSunflowers.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .classpath 3 | .project 4 | .settings 5 | *.userprefs 6 | packages 7 | src/csharp/bin 8 | src/csharp/obj 9 | src/test/csharp/bin 10 | src/test/csharp/obj 11 | TestResult.xml 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Building Maintainable Software 2 | ========== 3 | 4 | This is the example code that accompanies _Building Maintainable Software: Ten Guidelines for Future-Proof Code_ by Joost Visser. 5 | 6 | There are currently two editions of _Building Maintainable Software_: 7 | - The Java edition (ISBN print: 978-1-4919-5352-5, ISBN eBook: 978-1-4919-5348-8), available [at the O'Reilly webshop](http://shop.oreilly.com/product/0636920049159.do) and [at Amazon](http://www.amazon.com/Building-Maintainable-Software-Java-Edition-ebook/dp/B01B6WS86I). 8 | - The C# edition, currently submitted as a manuscript to O'Reilly Media. 9 | 10 | [Training videos](http://oreil.ly/1OVw1PM) are also available via O'Reilly Media. 11 | 12 | Both editions are the same except for the language of the code snippets and a bit of language-specific terminology (e.g., 'Eclipse' in the Java edition is 'Visual Studio' in the C# edition). 13 | 14 | Click the Download Zip button to the right to download example code. 15 | 16 | See an error? Report it [here](http://oreilly.com/catalog/errata.csp?isbn=9781491940662) for the Java edition, or simply fork and send us a pull request. 17 | 18 | About The Example Code 19 | ----------- 20 | 21 | The example code of the Java edition lives in `src/java` and `src/test/java`. The example code of the C# edition lives in `src/csharp` and `src/test/csharp`. Every `.java` file in `src/java` has a `.cs` file with the same name in `src/csharp` and the other way around. The same is true for the contents of the `src/test` directories. 22 | 23 | For the Java code, there is a `pom.xml` file in the root of this repository. This allows compiling the Java source files and running the unit tests using [Maven](https://maven.apache.org) by executing `mvn test`. 24 | 25 | For the C# code, there is a Visual Studio Solution file in the root of this repository, which references two projects (see the `.csproj` files in `src/csharp` and `src/test/csharp`). We compile the C# code and run the unit tests regularly using [Mono](http://www.mono-project.com) on MacOS and occasionally using Visual Studio. 26 | 27 | Both the Java and the C# editions have been written using O'Reilly's [Atlas](https://atlas.oreilly.com) platform in the [AsciiDoc](http://asciidoc.org) markup language. All code snippets displayed in the books are taken directly from this example code. The parts included in the books are between Java and C# comments of the form `// tag::NameOfTag[]` and `// end::NameOfTag[]`. All code not between such comments is just there to make everything compile and pass unit tests. 28 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | eu.sig.training 6 | maintainabilitybook 7 | 0.1-SNAPSHOT 8 | 9 | Software Improvement Group 10 | http://www.sig.eu 11 | 12 | 13 | git@git.atlas.oreilly.com:oreillymedia/sig-project.git 14 | 15 | 16 | 17 | junit 18 | junit 19 | 4.12 20 | test 21 | 22 | 23 | javax.servlet 24 | javax.servlet-api 25 | 3.1.0 26 | 27 | 28 | org.mockito 29 | mockito-core 30 | 1.10.19 31 | test 32 | 33 | 34 | javax.ws.rs 35 | javax.ws.rs-api 36 | 2.0.1 37 | 38 | 39 | org.apache.httpcomponents 40 | httpclient 41 | 4.5.1 42 | 43 | 44 | 45 | ${basedir}/src/java 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-compiler-plugin 50 | 3.3 51 | 52 | 1.7 53 | 1.7 54 | 55 | 56 | 57 | org.apache.maven.plugins 58 | maven-eclipse-plugin 59 | 2.10 60 | 61 | ${basedir} 62 | file:///${basedir}/java_eclipseformat.xml 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-surefire-plugin 68 | 2.18.1 69 | 70 | 71 | **/v1/AccountsTest.java 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-pmd-plugin 82 | 3.5 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/csharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | // Information about this assembly is defined by the following attributes. 3 | // Change them to the values specific to your project. 4 | 5 | [assembly: AssemblyTitle ("maintainabilitybook")] 6 | [assembly: AssemblyDescription ("")] 7 | [assembly: AssemblyConfiguration ("")] 8 | [assembly: AssemblyCompany ("")] 9 | [assembly: AssemblyProduct ("")] 10 | [assembly: AssemblyCopyright("Software Improvement Group")] 11 | [assembly: AssemblyTrademark ("")] 12 | [assembly: AssemblyCulture ("")] 13 | 14 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 15 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 16 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 17 | 18 | [assembly: AssemblyVersion ("1.0.*")] 19 | 20 | // The following attributes are used to specify the signing key for the assembly, 21 | // if desired. See the Mono documentation for more information about signing. 22 | 23 | //[assembly: AssemblyDelaySign(false)] 24 | //[assembly: AssemblyKeyFile("")] 25 | 26 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch02/BalancesServlet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | using System.Data; 4 | using System.Data.SqlClient; 5 | using System.Configuration; 6 | 7 | namespace eu.sig.training.ch02 8 | { 9 | public class BalancesServlet 10 | { 11 | // Visual Studio Code Analysis is right in pointing out that the following method has 12 | // security flaws. However, that's beside the point for this example. 13 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")] 14 | // tag::doGet[] 15 | public void DoGet(HttpRequest req, HttpResponse resp) 16 | { 17 | resp.ContentType = "application/json"; 18 | string command = "SELECT account, balance " + 19 | "FROM ACCTS WHERE id=" + req.Params[ 20 | ConfigurationManager.AppSettings["request.parametername"]]; 21 | SqlDataAdapter dataAdapter = new SqlDataAdapter(command, 22 | ConfigurationManager.AppSettings["handler.serverstring"]); 23 | DataSet dataSet = new DataSet(); 24 | dataAdapter.Fill(dataSet, "ACCTS"); 25 | DataTable dataTable = dataSet.Tables[0]; 26 | try 27 | { 28 | float totalBalance = 0; 29 | int rowNum = 0; 30 | resp.Write("{\"balances\":["); 31 | while (dataTable.Rows.GetEnumerator().MoveNext()) 32 | { 33 | rowNum++; 34 | DataRow results = (DataRow)dataTable.Rows.GetEnumerator().Current; 35 | // Assuming result is 9-digit bank account number, 36 | // validate with 11-test: 37 | int sum = 0; 38 | for (int i = 0; i < ((string)results["account"]).Length; i++) 39 | { 40 | sum = sum + (9 - i) * 41 | (int)Char.GetNumericValue(((string)results["account"])[i]); 42 | } 43 | if (sum % 11 == 0) 44 | { 45 | totalBalance += (float)results["balance"]; 46 | resp.Write($"{{\"{results["account"]}\":{results["balance"]}}}"); 47 | } 48 | if (rowNum == dataTable.Rows.Count) 49 | { 50 | resp.Write("],\n"); 51 | } 52 | else 53 | { 54 | resp.Write(","); 55 | } 56 | } 57 | resp.Write($"\"total\":{totalBalance}}}\n"); 58 | } 59 | catch (SqlException e) 60 | { 61 | Console.WriteLine($"SQL exception: {e.Message}"); 62 | } 63 | } 64 | // end::doGet[] 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch02/BoardFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace eu.sig.training.ch02 4 | { 5 | public class BoardFactory 6 | { 7 | // tag::createBoard[] 8 | public Board CreateBoard(Square[,] grid) 9 | { 10 | Debug.Assert(grid != null); 11 | 12 | Board board = new Board(grid); 13 | 14 | int width = board.Width; 15 | int height = board.Height; 16 | for (int x = 0; x < width; x++) 17 | { 18 | for (int y = 0; y < height; y++) 19 | { 20 | Square square = grid[x, y]; 21 | foreach (Direction dir in Direction.Values) 22 | { 23 | int dirX = (width + x + dir.DeltaX) % width; 24 | int dirY = (height + y + dir.DeltaY) % height; 25 | Square neighbour = grid[dirX, dirY]; 26 | square.Link(neighbour, dir); 27 | } 28 | } 29 | } 30 | 31 | return board; 32 | } 33 | // end::createBoard[] 34 | } 35 | 36 | public class Board 37 | { 38 | public Board(Square[,] grid) { } 39 | 40 | public int Width { get; set; } 41 | 42 | public int Height { get; set; } 43 | } 44 | 45 | public class Square 46 | { 47 | public void Link(Square neighbour, Direction dir) { } 48 | } 49 | 50 | public class Direction 51 | { 52 | 53 | public static Direction[] Values { get; set; } 54 | 55 | public int DeltaY { get; set; } 56 | 57 | public int DeltaX { get; set; } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch02/Employees.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch02 4 | { 5 | public static class Employees 6 | { 7 | // tag::printDepartmentEmployees[] 8 | public static void PrintDepartmentEmployees(string department) 9 | { 10 | Query q = new Query(); 11 | foreach (Employee e in q.AddColumn("FamilyName") 12 | .AddColumn("Initials") 13 | .AddColumn("GivenName") 14 | .AddColumn("AddressLine1") 15 | .AddColumn("ZIPcode") 16 | .AddColumn("City") 17 | .AddTable("EMPLOYEES") 18 | .AddWhere($"EmployeeDep='{department}'") 19 | .Execute()) 20 | { 21 | Console.WriteLine($@"
22 | {e.FamilyName}, {e.Initials}
" + 23 | "{e.AddressLine1}
{e.ZipCode}{e.City}
"); 24 | } 25 | } 26 | // end::printDepartmentEmployees[] 27 | } 28 | 29 | class Query 30 | { 31 | 32 | public Query AddColumn(string s) 33 | { 34 | return null; 35 | } 36 | 37 | public Employee[] Execute() 38 | { 39 | return null; 40 | } 41 | 42 | public Query AddWhere(string s) 43 | { 44 | return null; 45 | } 46 | 47 | public Query AddTable(string s) 48 | { 49 | return null; 50 | } 51 | } 52 | 53 | class Employee 54 | { 55 | 56 | public string FamilyName { get; set; } 57 | 58 | public string AddressLine1 { get; set; } 59 | 60 | public string ZipCode { get; set; } 61 | 62 | public string City { get; set; } 63 | 64 | public string Initials { get; set; } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch02/Level.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace eu.sig.training.ch02 4 | { 5 | 6 | public class Level 7 | { 8 | private bool inProgress; 9 | private readonly IList observers; 10 | 11 | Level(IList observers) 12 | { 13 | this.observers = observers; 14 | } 15 | 16 | // tag::start[] 17 | public void Start() 18 | { 19 | if (inProgress) 20 | { 21 | return; 22 | } 23 | inProgress = true; 24 | // Update observers if player died: 25 | if (!IsAnyPlayerAlive()) 26 | { 27 | foreach (LevelObserver o in observers) 28 | { 29 | o.LevelLost(); 30 | } 31 | } 32 | // Update observers if all pellets eaten: 33 | if (RemainingPellets() == 0) 34 | { 35 | foreach (LevelObserver o in observers) 36 | { 37 | o.LevelWon(); 38 | } 39 | } 40 | } 41 | // end::start[] 42 | 43 | // tag::updateObservers[] 44 | private void UpdateObservers() 45 | { 46 | // Update observers if player died: 47 | if (!IsAnyPlayerAlive()) 48 | { 49 | foreach (LevelObserver o in observers) 50 | { 51 | o.LevelLost(); 52 | } 53 | } 54 | // Update observers if all pellets eaten: 55 | if (RemainingPellets() == 0) 56 | { 57 | foreach (LevelObserver o in observers) 58 | { 59 | o.LevelWon(); 60 | } 61 | } 62 | } 63 | // end::updateObservers[] 64 | 65 | // tag::updateObserversPlayerDied[] 66 | private void UpdateObserversPlayerDied() 67 | { 68 | if (!IsAnyPlayerAlive()) 69 | { 70 | foreach (LevelObserver o in observers) 71 | { 72 | o.LevelLost(); 73 | } 74 | } 75 | } 76 | 77 | // end::updateObserversPlayerDied[] 78 | 79 | // tag::updateObserversPelletsEaten[] 80 | private void UpdateObserversPelletsEaten() 81 | { 82 | if (RemainingPellets() == 0) 83 | { 84 | foreach (LevelObserver o in observers) 85 | { 86 | o.LevelWon(); 87 | } 88 | } 89 | } 90 | // end::updateObserversPelletsEaten[] 91 | 92 | private int RemainingPellets() 93 | { 94 | return 0; 95 | } 96 | 97 | private bool IsAnyPlayerAlive() 98 | { 99 | return false; 100 | } 101 | } 102 | 103 | class LevelObserver 104 | { 105 | public void LevelLost() { } 106 | public void LevelWon() { } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch02/LevelHelper.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch02 2 | { 3 | 4 | public class LevelHelper 5 | { 6 | private bool inProgress; 7 | 8 | // tag::firstStepStart[] 9 | public void Start() 10 | { 11 | if (inProgress) 12 | { 13 | return; 14 | } 15 | inProgress = true; 16 | } 17 | // end::firstStepStart[] 18 | } 19 | 20 | public class ExtractMethod 21 | { 22 | private bool inProgress; 23 | 24 | // tag::extractMethodStart[] 25 | public void Start() 26 | { 27 | if (inProgress) 28 | { 29 | return; 30 | } 31 | inProgress = true; 32 | UpdateObservers(); 33 | } 34 | // end::extractMethodStart[] 35 | 36 | // tag::updateObservers[] 37 | public void UpdateObservers() 38 | { 39 | UpdateObserversPlayerDied(); 40 | UpdateObserversPelletsEaten(); 41 | } 42 | // end::updateObservers[] 43 | 44 | private void UpdateObserversPlayerDied() { } 45 | 46 | private void UpdateObserversPelletsEaten() { } 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch02/v1/BoardFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace eu.sig.training.ch02.v1 4 | { 5 | public class BoardFactory 6 | { 7 | // tag::createBoard[] 8 | public Board CreateBoard(Square[,] grid) 9 | { 10 | Debug.Assert(grid != null); 11 | 12 | Board board = new Board(grid); 13 | 14 | int width = board.Width; 15 | int height = board.Height; 16 | for (int x = 0; x < width; x++) 17 | { 18 | for (int y = 0; y < height; y++) 19 | { 20 | Square square = grid[x, y]; 21 | foreach (Direction dir in Direction.Values) 22 | { 23 | SetLink(square, dir, x, y, width, height, grid); 24 | } 25 | } 26 | } 27 | 28 | return board; 29 | } 30 | // end::createBoard[] 31 | 32 | // tag::setLink[] 33 | private void SetLink(Square square, Direction dir, int x, int y, 34 | int width, int height, Square[,] grid) 35 | { 36 | int dirX = (width + x + dir.DeltaX) % width; 37 | int dirY = (height + y + dir.DeltaY) % height; 38 | Square neighbour = grid[dirX, dirY]; 39 | square.Link(neighbour, dir); 40 | } 41 | // end::setLink[] 42 | } 43 | 44 | public class Board 45 | { 46 | public Board(Square[,] grid) { } 47 | 48 | public int Width { get; set; } 49 | public int Height { get; set; } 50 | } 51 | 52 | public class Square 53 | { 54 | public void Link(Square neighbour, Direction dir) { } 55 | } 56 | 57 | public class Direction 58 | { 59 | 60 | public static Direction[] Values { get; set; } 61 | 62 | public int DeltaY { get; set; } 63 | 64 | public int DeltaX { get; set; } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch02/v2/BoardFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace eu.sig.training.ch02.v2 4 | { 5 | public class BoardFactory 6 | { 7 | // tag::createBoard[] 8 | public Board CreateBoard(Square[,] grid) 9 | { 10 | return new BoardCreator(grid).Create(); 11 | } 12 | // end::createBoard[] 13 | } 14 | 15 | // tag::BoardCreator[] 16 | internal class BoardCreator 17 | { 18 | private Square[,] grid; 19 | private Board board; 20 | private int width; 21 | private int height; 22 | 23 | internal BoardCreator(Square[,] grid) 24 | { 25 | Debug.Assert(grid != null); 26 | this.grid = grid; 27 | this.board = new Board(grid); 28 | this.width = board.Width; 29 | this.height = board.Height; 30 | } 31 | 32 | internal Board Create() 33 | { 34 | for (int x = 0; x < width; x++) 35 | { 36 | for (int y = 0; y < height; y++) 37 | { 38 | Square square = grid[x, y]; 39 | foreach (Direction dir in Direction.Values) 40 | { 41 | SetLink(square, dir, x, y); 42 | } 43 | } 44 | } 45 | return this.board; 46 | } 47 | 48 | private void SetLink(Square square, Direction dir, int x, int y) 49 | { 50 | int dirX = (width + x + dir.DeltaX) % width; 51 | int dirY = (height + y + dir.DeltaY) % height; 52 | Square neighbour = grid[dirX, dirY]; 53 | square.Link(neighbour, dir); 54 | } 55 | } 56 | 57 | // end::BoardCreator[] 58 | 59 | public class Board 60 | { 61 | public Board(Square[,] grid) 62 | { 63 | } 64 | 65 | public int Width { get; set; } 66 | 67 | public int Height { get; set; } 68 | } 69 | 70 | public class Square 71 | { 72 | public void Link(Square neighbour, Direction dir) 73 | { 74 | } 75 | } 76 | 77 | public class Direction 78 | { 79 | public static Direction[] Values { get; set; } 80 | 81 | public int DeltaY { get; set; } 82 | 83 | public int DeltaX { get; set; } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/Flag.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace eu.sig.training.ch03 5 | { 6 | 7 | public class Flag 8 | { 9 | public IList Colors { get; } 10 | 11 | public Flag(params Color[] colors) 12 | { 13 | Colors = new List(colors); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/FlagFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03 5 | { 6 | 7 | public class FlagFactory 8 | { 9 | // tag::getFlag[] 10 | public IList GetFlagColors(Nationality nationality) 11 | { 12 | List result; 13 | switch (nationality) 14 | { 15 | case Nationality.DUTCH: 16 | result = new List { Color.Red, Color.White, Color.Blue }; 17 | break; 18 | case Nationality.GERMAN: 19 | result = new List { Color.Black, Color.Red, Color.Yellow }; 20 | break; 21 | case Nationality.BELGIAN: 22 | result = new List { Color.Black, Color.Yellow, Color.Red }; 23 | break; 24 | case Nationality.FRENCH: 25 | result = new List { Color.Blue, Color.White, Color.Red }; 26 | break; 27 | case Nationality.ITALIAN: 28 | result = new List { Color.Green, Color.White, Color.Red }; 29 | break; 30 | case Nationality.UNCLASSIFIED: 31 | default: 32 | result = new List { Color.Gray }; 33 | break; 34 | } 35 | return result; 36 | } 37 | // end::getFlag[] 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/FlagFactoryOops.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03 5 | { 6 | public class FlagFactoryOops 7 | { 8 | public IList GetFlagColors(Nationality nationality) 9 | { 10 | List result; 11 | switch (nationality) 12 | { 13 | // tag::getFlag[] 14 | case Nationality.DUTCH: 15 | result = new List { Color.Red, Color.White, Color.Blue }; 16 | // end::getFlag[] 17 | break; 18 | // tag::getFlag[] 19 | case Nationality.LUXEMBOURGER: 20 | result = new List { Color.Red, Color.White, Color.LightBlue }; 21 | break; 22 | case Nationality.GERMAN: 23 | // end::getFlag[] 24 | result = new List { Color.Black, Color.Red, Color.Yellow }; 25 | break; 26 | case Nationality.BELGIAN: 27 | result = new List { Color.Black, Color.Yellow, Color.Red }; 28 | break; 29 | case Nationality.FRENCH: 30 | result = new List { Color.Blue, Color.White, Color.Red }; 31 | break; 32 | case Nationality.ITALIAN: 33 | result = new List { Color.Green, Color.White, Color.Red }; 34 | break; 35 | case Nationality.UNCLASSIFIED: 36 | default: 37 | result = new List { Color.Gray }; 38 | break; 39 | } 40 | return result; 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/FlagFactoryWithMap.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace eu.sig.training.ch03 5 | { 6 | 7 | public class FlagFactoryWithMap 8 | { 9 | 10 | // tag::getFlag[] 11 | private static Dictionary> FLAGS = 12 | new Dictionary>(); 13 | 14 | static FlagFactoryWithMap() 15 | { 16 | FLAGS[Nationality.DUTCH] = new List{ Color.Red, Color.White, 17 | Color.Blue }; 18 | FLAGS[Nationality.GERMAN] = new List{ Color.Black, Color.Red, 19 | Color.Yellow }; 20 | FLAGS[Nationality.BELGIAN] = new List{ Color.Black, Color.Yellow, 21 | Color.Red }; 22 | FLAGS[Nationality.FRENCH] = new List{ Color.Blue, Color.White, 23 | Color.Red }; 24 | FLAGS[Nationality.ITALIAN] = new List{ Color.Green, Color.White, 25 | Color.Red }; 26 | } 27 | 28 | public IList GetFlagColors(Nationality nationality) 29 | { 30 | IList colors = FLAGS[nationality]; 31 | return colors ?? new List { Color.Gray }; 32 | } 33 | // end::getFlag[] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/Nationality.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch03 2 | { 3 | 4 | public enum Nationality 5 | { 6 | DUTCH, 7 | GERMAN, 8 | BELGIAN, 9 | FRENCH, 10 | ITALIAN, 11 | LUXEMBOURGER, 12 | UNCLASSIFIED 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/binarytree/BinaryTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch03.binarytree 4 | { 5 | 6 | public class BinaryTreeNode where T : IComparable 7 | { 8 | public T Value { get; set; } 9 | public BinaryTreeNode Left { get; set; } 10 | public BinaryTreeNode Right { get; set; } 11 | 12 | public BinaryTreeNode(T value) 13 | { 14 | this.Value = value; 15 | } 16 | 17 | public void Insert(T value) 18 | { 19 | if (value.CompareTo(this.Value) < 0) 20 | { 21 | if (Left != null) 22 | { 23 | Left.Insert(value); 24 | } 25 | else 26 | { 27 | Left = new BinaryTreeNode(value); 28 | } 29 | } 30 | else 31 | { 32 | if (Right != null) 33 | { 34 | Right.Insert(value); 35 | } 36 | else 37 | { 38 | Right = new BinaryTreeNode(value); 39 | } 40 | } 41 | } 42 | 43 | public bool IsLeaf() 44 | { 45 | return Left == null && Right == null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/binarytree/TreeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch03.binarytree 4 | { 5 | [Serializable] 6 | public class TreeException : SystemException 7 | { 8 | public TreeException(string msg) : base(msg) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/binarytree/v1/BinaryTreeSearch.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch03.binarytree.v1 2 | { 3 | 4 | public class BinaryTreeSearch 5 | { 6 | 7 | // tag::calculateDepth[] 8 | public static int CalculateDepth(BinaryTreeNode t, int n) 9 | { 10 | int depth = 0; 11 | if (t.Value == n) 12 | { 13 | return depth; 14 | } 15 | else 16 | { 17 | if (n < t.Value) 18 | { 19 | BinaryTreeNode left = t.Left; 20 | if (left == null) 21 | { 22 | throw new TreeException("Value not found in tree!"); 23 | } 24 | else 25 | { 26 | return 1 + CalculateDepth(left, n); 27 | } 28 | } 29 | else 30 | { 31 | BinaryTreeNode right = t.Right; 32 | if (right == null) 33 | { 34 | throw new TreeException("Value not found in tree!"); 35 | } 36 | else 37 | { 38 | return 1 + CalculateDepth(right, n); 39 | } 40 | } 41 | } 42 | } 43 | // end::calculateDepth[] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/binarytree/v2/BinaryTreeSearch.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch03.binarytree.v2 2 | { 3 | 4 | public class BinaryTreeSearch 5 | { 6 | 7 | // tag::calculateDepth[] 8 | public static int CalculateDepth(BinaryTreeNode t, int n) 9 | { 10 | int depth = 0; 11 | if (t.Value == n) 12 | { 13 | return depth; 14 | } 15 | if ((n < t.Value) && (t.Left != null)) 16 | { 17 | return 1 + CalculateDepth(t.Left, n); 18 | } 19 | if ((n > t.Value) && (t.Right != null)) 20 | { 21 | return 1 + CalculateDepth(t.Right, n); 22 | } 23 | throw new TreeException("Value not found in tree!"); 24 | } 25 | // end::calculateDepth[] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/binarytree/v3/BinaryTreeSearch.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch03.binarytree.v3 2 | { 3 | 4 | public class BinaryTreeSearch 5 | { 6 | 7 | // tag::calculateDepth[] 8 | public static int CalculateDepth(BinaryTreeNode t, int n) 9 | { 10 | int depth = 0; 11 | if (t.Value == n) 12 | { 13 | return depth; 14 | } 15 | else 16 | { 17 | return TraverseByValue(t, n); 18 | } 19 | } 20 | 21 | private static int TraverseByValue(BinaryTreeNode t, int n) 22 | { 23 | BinaryTreeNode childNode = GetChildNode(t, n); 24 | if (childNode == null) 25 | { 26 | throw new TreeException("Value not found in tree!"); 27 | } 28 | else 29 | { 30 | return 1 + CalculateDepth(childNode, n); 31 | } 32 | } 33 | 34 | private static BinaryTreeNode GetChildNode( 35 | BinaryTreeNode t, int n) 36 | { 37 | if (n < t.Value) 38 | { 39 | return t.Left; 40 | } 41 | else 42 | { 43 | return t.Right; 44 | } 45 | } 46 | // end::calculateDepth[] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/BelgianFlag.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | 7 | public class BelgianFlag : IFlag 8 | { 9 | public IList Colors 10 | { 11 | get 12 | { 13 | return new List { Color.Black, Color.Red, Color.Yellow }; 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/DefaultFlag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | public class DefaultFlag : IFlag 7 | { 8 | public IList Colors 9 | { 10 | get 11 | { 12 | return new List { Color.Gray }; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/DutchFlag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | 7 | // tag::DutchFlag[] 8 | public class DutchFlag : IFlag 9 | { 10 | public IList Colors 11 | { 12 | get 13 | { 14 | return new List { Color.Red, Color.White, Color.Blue }; 15 | } 16 | } 17 | } 18 | // end::DutchFlag[] 19 | } 20 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/FlagFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | 7 | public class FlagFactory 8 | { 9 | 10 | // tag::getFlag[] 11 | private static readonly Dictionary FLAGS = 12 | new Dictionary(); 13 | 14 | static FlagFactory() 15 | { 16 | FLAGS[Nationality.DUTCH] = new DutchFlag(); 17 | FLAGS[Nationality.GERMAN] = new GermanFlag(); 18 | FLAGS[Nationality.BELGIAN] = new BelgianFlag(); 19 | FLAGS[Nationality.FRENCH] = new FrenchFlag(); 20 | FLAGS[Nationality.ITALIAN] = new ItalianFlag(); 21 | } 22 | 23 | public IList GetFlagColors(Nationality nationality) 24 | { 25 | IFlag flag = FLAGS[nationality]; 26 | flag = flag ?? new DefaultFlag(); 27 | return flag.Colors; 28 | } 29 | // end::getFlag[] 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/FrenchFlag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | 7 | public class FrenchFlag : IFlag 8 | { 9 | public IList Colors 10 | { 11 | get 12 | { 13 | return new List { Color.Blue, Color.White, Color.Red }; 14 | } 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/GermanFlag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | 7 | public class GermanFlag : IFlag 8 | { 9 | public IList Colors 10 | { 11 | get 12 | { 13 | return new List { Color.Black, Color.Red, Color.Yellow }; 14 | } 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/IFlag.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | 7 | // tag::Flag[] 8 | public interface IFlag 9 | { 10 | IList Colors { get; } 11 | } 12 | // end::Flag[] 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch03/withmapandtypes/ItalianFlag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch03.withmapandtypes 5 | { 6 | 7 | // tag::ItalianFlag[] 8 | public class ItalianFlag : IFlag 9 | { 10 | public IList Colors 11 | { 12 | get 13 | { 14 | return new List { Color.Green, Color.White, Color.Red }; 15 | } 16 | } 17 | } 18 | // end::ItalianFlag[] 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/BusinessException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch04 4 | { 5 | [Serializable] 6 | public class BusinessException : Exception 7 | { 8 | public BusinessException(string message) : base(message) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/Clones.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04 2 | { 3 | public class Clones 4 | { 5 | private string givenName; 6 | private string familyName; 7 | private float pageWidthInCm; 8 | 9 | // tag::one-six-line-clone[] 10 | public void SetGivenName(string givenName) 11 | { 12 | this.givenName = givenName; 13 | } 14 | 15 | public void SetFamilyName(string familyName) 16 | { 17 | this.familyName = familyName; 18 | } 19 | // end::one-six-line-clone[] 20 | 21 | public string GetGivenName() 22 | { 23 | return givenName; 24 | } 25 | 26 | public string GetFamilyName() 27 | { 28 | return familyName; 29 | } 30 | 31 | // tag::type-2-clone[] 32 | public void SetPageWidthInInches(float newWidth) 33 | { 34 | float cmPerInch = 2.54f; 35 | this.pageWidthInCm = newWidth * cmPerInch; 36 | // A few more lines. 37 | } 38 | 39 | public void SetPageWidthInPoints(float newWidth) 40 | { 41 | float cmPerPoint = 0.0352777f; 42 | this.pageWidthInCm = newWidth * cmPerPoint; 43 | // A few more lines (same as in setPageWidthInInches). 44 | } 45 | // end::type-2-clone[] 46 | 47 | public float GetPageWidthInCm() 48 | { 49 | return pageWidthInCm; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/Money.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04 2 | { 3 | public class Money 4 | { 5 | public bool GreaterThan(int limit) 6 | { 7 | return true; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v1/Accounts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch04.v1 4 | { 5 | public static class Accounts 6 | { 7 | 8 | public static CheckingAccount FindAcctByNumber(string number) 9 | { 10 | return new CheckingAccount(); 11 | } 12 | 13 | // tag::isValid[] 14 | public static bool IsValid(string number) 15 | { 16 | int sum = 0; 17 | for (int i = 0; i < number.Length; i++) 18 | { 19 | sum = sum + (9 - i) * (int)Char.GetNumericValue(number[i]); 20 | } 21 | return sum % 11 == 0; 22 | } 23 | // end::isValid[] 24 | } 25 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v1/CheckingAccount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace eu.sig.training.ch04.v1 3 | { 4 | // tag::CheckingAccount[] 5 | public class CheckingAccount 6 | { 7 | private int transferLimit = 100; 8 | 9 | public Transfer MakeTransfer(String counterAccount, Money amount) 10 | { 11 | // 1. Check withdrawal limit: 12 | if (amount.GreaterThan(this.transferLimit)) 13 | { 14 | throw new BusinessException("Limit exceeded!"); 15 | } 16 | // 2. Assuming result is 9-digit bank account number, validate 11-test: 17 | int sum = 0; 18 | for (int i = 0; i < counterAccount.Length; i++) 19 | { 20 | sum = sum + (9 - i) * (int)Char.GetNumericValue( 21 | counterAccount[i]); 22 | } 23 | if (sum % 11 == 0) 24 | { 25 | // 3. Look up counter account and make transfer object: 26 | CheckingAccount acct = Accounts.FindAcctByNumber(counterAccount); 27 | Transfer result = new Transfer(this, acct, amount); 28 | return result; 29 | } 30 | else 31 | { 32 | throw new BusinessException("Invalid account number!"); 33 | } 34 | } 35 | } 36 | // end::CheckingAccount[] 37 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v1/SavingsAccount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch04.v1 4 | { 5 | // tag::SavingsAccount[] 6 | public class SavingsAccount 7 | { 8 | public CheckingAccount RegisteredCounterAccount { get; set; } 9 | 10 | public Transfer makeTransfer(string counterAccount, Money amount) 11 | { 12 | // 1. Assuming result is 9-digit bank account number, validate 11-test: 13 | int sum = 0; // <1> 14 | for (int i = 0; i < counterAccount.Length; i++) 15 | { 16 | sum = sum + (9 - i) * (int)Char.GetNumericValue( 17 | counterAccount[i]); 18 | } 19 | if (sum % 11 == 0) 20 | { 21 | // 2. Look up counter account and make transfer object: 22 | CheckingAccount acct = Accounts.FindAcctByNumber(counterAccount); 23 | Transfer result = new Transfer(this, acct, amount); // <2> 24 | // 3. Check whether withdrawal is to registered counter account: 25 | if (result.CounterAccount.Equals(this.RegisteredCounterAccount)) 26 | { 27 | return result; 28 | } 29 | else 30 | { 31 | throw new BusinessException("Counter-account not registered!"); 32 | } 33 | } 34 | else 35 | { 36 | throw new BusinessException("Invalid account number!!"); 37 | } 38 | } 39 | } 40 | // end::SavingsAccount[] 41 | } 42 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v1/Transfer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04.v1 2 | { 3 | 4 | public class Transfer 5 | { 6 | public CheckingAccount CounterAccount { get; set; } 7 | 8 | public Transfer(CheckingAccount acct1, CheckingAccount acct2, Money m) 9 | { 10 | } 11 | 12 | public Transfer(SavingsAccount acct1, CheckingAccount acct2, Money m) 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v2/Accounts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch04.v2 4 | { 5 | 6 | public static class Accounts 7 | { 8 | 9 | public static CheckingAccount FindAcctByNumber(string number) 10 | { 11 | return new CheckingAccount(); 12 | } 13 | 14 | // tag::isValid[] 15 | public static bool IsValid(string number) 16 | { 17 | int sum = 0; 18 | for (int i = 0; i < number.Length; i++) 19 | { 20 | sum = sum + (9 - i) * (int)Char.GetNumericValue(number[i]); 21 | } 22 | return sum % 11 == 0; 23 | } 24 | // end::isValid[] 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v2/CheckingAccount.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04.v2 2 | { 3 | 4 | // tag::CheckingAccount[] 5 | public class CheckingAccount 6 | { 7 | private int transferLimit = 100; 8 | 9 | public Transfer MakeTransfer(string counterAccount, Money amount) 10 | { 11 | // 1. Check withdrawal limit: 12 | if (amount.GreaterThan(this.transferLimit)) 13 | { 14 | throw new BusinessException("Limit exceeded!"); 15 | } 16 | if (Accounts.IsValid(counterAccount)) 17 | { // <1> 18 | // 2. Look up counter account and make transfer object: 19 | CheckingAccount acct = Accounts.FindAcctByNumber(counterAccount); 20 | Transfer result = new Transfer(this, acct, amount); // <2> 21 | return result; 22 | } 23 | else 24 | { 25 | throw new BusinessException("Invalid account number!"); 26 | } 27 | } 28 | } 29 | // end::CheckingAccount[] 30 | } 31 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v2/SavingsAccount.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04.v2 2 | { 3 | 4 | // tag::SavingsAccount[] 5 | public class SavingsAccount 6 | { 7 | public CheckingAccount RegisteredCounterAccount { get; set; } 8 | 9 | public Transfer MakeTransfer(string counterAccount, Money amount) 10 | { 11 | // 1. Assuming result is 9-digit bank account number, validate 11-test: 12 | if (Accounts.IsValid(counterAccount)) 13 | { // <1> 14 | // 2. Look up counter account and make transfer object: 15 | CheckingAccount acct = Accounts.FindAcctByNumber(counterAccount); 16 | Transfer result = new Transfer(this, acct, amount); // <2> 17 | if (result.CounterAccount.Equals(this.RegisteredCounterAccount)) 18 | { 19 | return result; 20 | } 21 | else 22 | { 23 | throw new BusinessException("Counter-account not registered!"); 24 | } 25 | } 26 | else 27 | { 28 | throw new BusinessException("Invalid account number!!"); 29 | } 30 | } 31 | } 32 | // end::SavingsAccount[] 33 | } 34 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v2/Transfer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04.v2 2 | { 3 | 4 | public class Transfer 5 | { 6 | public CheckingAccount CounterAccount { get; set; } 7 | 8 | public Transfer(CheckingAccount acct1, CheckingAccount acct2, Money m) 9 | { 10 | } 11 | 12 | public Transfer(SavingsAccount acct1, CheckingAccount acct2, Money m) 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v3/Account.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch04.v3 4 | { 5 | 6 | // tag::Account[] 7 | public class Account 8 | { 9 | public virtual Transfer MakeTransfer(string counterAccount, Money amount) 10 | { 11 | // 1. Assuming result is 9-digit bank account number, validate 11-test: 12 | int sum = 0; // <1> 13 | for (int i = 0; i < counterAccount.Length; i++) 14 | { 15 | sum = sum + (9 - i) * (int)Char. 16 | GetNumericValue(counterAccount[i]); 17 | } 18 | if (sum % 11 == 0) 19 | { 20 | // 2. Look up counter account and make transfer object: 21 | CheckingAccount acct = Accounts.FindAcctByNumber(counterAccount); 22 | Transfer result = new Transfer(this, acct, amount); // <2> 23 | return result; 24 | } 25 | else 26 | { 27 | throw new BusinessException("Invalid account number!"); 28 | } 29 | } 30 | } 31 | // end::Account[] 32 | 33 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v3/Accounts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace eu.sig.training.ch04.v3 5 | { 6 | 7 | public static class Accounts 8 | { 9 | 10 | // The Java version of the Account class does not have a string Number as property, 11 | // and the Java edition of the book is already in print. So we add an external 12 | // association of Accounts and their numbers. 13 | public static Dictionary ACCOUNTS = new Dictionary(); 14 | public static Dictionary NUMBERS = new Dictionary(); 15 | 16 | public static CheckingAccount FindAcctByNumber(string number) 17 | { 18 | var myAccount = ACCOUNTS[number]; 19 | if (myAccount is CheckingAccount) 20 | { 21 | return (CheckingAccount)myAccount; 22 | } 23 | else 24 | { 25 | throw new BusinessException("Not a checking account."); 26 | } 27 | } 28 | 29 | public static T MakeAccount(string number) where T : Account, new() 30 | { 31 | var myAccount = new T(); 32 | ACCOUNTS[number] = myAccount; 33 | NUMBERS[myAccount] = number; 34 | return myAccount; 35 | } 36 | 37 | public static string GetAccountNumber(Account acct) 38 | { 39 | return NUMBERS[acct]; 40 | } 41 | 42 | // tag::isValid[] 43 | public static bool IsValid(string number) 44 | { 45 | int sum = 0; 46 | for (int i = 0; i < number.Length; i++) 47 | { 48 | sum = sum + (9 - i) * (int)Char.GetNumericValue(number[i]); 49 | } 50 | return sum % 11 == 0; 51 | } 52 | // end::isValid[] 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v3/CheckingAccount.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04.v3 2 | { 3 | 4 | // tag::CheckingAccount[] 5 | public class CheckingAccount : Account 6 | { 7 | private int transferLimit = 100; 8 | 9 | public override Transfer MakeTransfer(string counterAccount, Money amount) 10 | { 11 | if (amount.GreaterThan(this.transferLimit)) 12 | { 13 | throw new BusinessException("Limit exceeded!"); 14 | } 15 | return base.MakeTransfer(counterAccount, amount); 16 | } 17 | } 18 | // end::CheckingAccount[] 19 | 20 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v3/SavingsAccount.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04.v3 2 | { 3 | 4 | // tag::SavingsAccount[] 5 | public class SavingsAccount : Account 6 | { 7 | public CheckingAccount RegisteredCounterAccount { get; set; } 8 | 9 | public override Transfer MakeTransfer(string counterAccount, Money amount) 10 | { 11 | Transfer result = base.MakeTransfer(counterAccount, amount); 12 | if (result.CounterAccount.Equals(this.RegisteredCounterAccount)) 13 | { 14 | return result; 15 | } 16 | else 17 | { 18 | throw new BusinessException("Counter-account not registered!"); 19 | } 20 | } 21 | } 22 | // end::SavingsAccount[] 23 | 24 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v3/Transfer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch04.v3 2 | { 3 | 4 | public class Transfer 5 | { 6 | public CheckingAccount CounterAccount { get; set; } 7 | 8 | public Transfer(Account acct1, CheckingAccount acct2, Money m) 9 | { 10 | CounterAccount = acct2; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v4/Account.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using eu.sig.training.ch04.v3; 3 | 4 | namespace eu.sig.training.ch04.v4 5 | { 6 | 7 | // tag::Account[] 8 | public class Account 9 | { 10 | public Transfer MakeTransfer(string counterAccount, Money amount) 11 | { 12 | if (IsValid(counterAccount)) 13 | { 14 | CheckingAccount acct = Accounts.FindAcctByNumber(counterAccount); 15 | return new Transfer(this, acct, amount); 16 | } 17 | else 18 | { 19 | throw new BusinessException("Invalid account number!"); 20 | } 21 | } 22 | 23 | public static bool IsValid(string number) 24 | { 25 | int sum = 0; 26 | for (int i = 0; i < number.Length; i++) 27 | { 28 | sum = sum + (9 - i) * (int)Char.GetNumericValue(number[i]); 29 | } 30 | return sum % 11 == 0; 31 | } 32 | } 33 | // end::Account[] 34 | 35 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v4/Accounts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using eu.sig.training.ch04.v3; 3 | 4 | namespace eu.sig.training.ch04.v4 5 | { 6 | 7 | public static class Accounts 8 | { 9 | public static CheckingAccount FindAcctByNumber(string number) 10 | { 11 | return new CheckingAccount(); 12 | } 13 | 14 | // Version that should make tests succeed (not used in book): 15 | public static bool IsValid(string number) 16 | { 17 | if (number.Length != 9) 18 | { 19 | return false; 20 | } 21 | int sum = 0; 22 | for (int i = 0; i < number.Length; i++) 23 | { 24 | if (!Char.IsDigit(number[i])) 25 | { 26 | return false; 27 | } 28 | sum = sum + (9 - i) * (int)Char.GetNumericValue(number[i]); 29 | } 30 | return sum % 11 == 0; 31 | } 32 | 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch04/v4/Transfer.cs: -------------------------------------------------------------------------------- 1 | using eu.sig.training.ch04.v3; 2 | 3 | namespace eu.sig.training.ch04.v4 4 | { 5 | 6 | public class Transfer 7 | { 8 | public CheckingAccount CounterAccount { get; set; } 9 | 10 | public Transfer(Account acct1, CheckingAccount acct2, Money m) 11 | { 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch05/boardpanel/v1/BoardPanel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch05.boardpanel.v1 5 | { 6 | public class BoardPanel 7 | { 8 | // tag::render[] 9 | /// 10 | /// Renders a single square on the given graphics context on the specified 11 | /// rectangle. 12 | /// 13 | /// The square to render. 14 | /// The graphics context to draw on. 15 | /// The x position to start drawing. 16 | /// The y position to start drawing. 17 | /// The width of this square (in pixels.) 18 | /// The height of this square (in pixels.) 19 | private void Render(Square square, Graphics g, int x, int y, int w, int h) 20 | { 21 | square.Sprite.Draw(g, x, y, w, h); 22 | foreach (Unit unit in square.Occupants) 23 | { 24 | unit.Sprite.Draw(g, x, y, w, h); 25 | } 26 | } 27 | // end::render[] 28 | 29 | private class Sprite 30 | { 31 | public void Draw(Graphics g, int x, int y, int w, int h) 32 | { 33 | 34 | } 35 | } 36 | 37 | private class Unit 38 | { 39 | public Sprite Sprite { get; set; } 40 | } 41 | 42 | private class Square : Unit 43 | { 44 | 45 | public IList Occupants { get; set; } 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch05/boardpanel/v2/BoardPanel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace eu.sig.training.ch05.boardpanel.v2 5 | { 6 | 7 | public class BoardPanel 8 | { 9 | // tag::render[] 10 | /// 11 | /// Renders a single square on the given graphics context on the specified 12 | /// rectangle. 13 | /// 14 | /// The square to render. 15 | /// The graphics context to draw on. 16 | /// The position and dimension for rendering the square. 17 | private void Render(Square square, Graphics g, Rectangle r) 18 | { 19 | Point position = r.Position; 20 | square.Sprite.Draw(g, position.X, position.Y, r.Width, r.Height); 21 | foreach (Unit unit in square.Occupants) 22 | { 23 | unit.Sprite.Draw(g, position.X, position.Y, r.Width, r.Height); 24 | } 25 | } 26 | // end::render[] 27 | 28 | private class Sprite 29 | { 30 | public void Draw(Graphics g, int x, int y, int w, int h) 31 | { 32 | 33 | } 34 | } 35 | 36 | private class Unit 37 | { 38 | public Sprite Sprite { get; set; } 39 | } 40 | 41 | private class Square : Unit 42 | { 43 | 44 | public IList Occupants { get; set; } 45 | 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch05/boardpanel/v2/Rectangle.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace eu.sig.training.ch05.boardpanel.v2 4 | { 5 | // tag::Rectangle[] 6 | public class Rectangle 7 | { 8 | public Point Position { get; set; } 9 | 10 | public int Width { get; set; } 11 | 12 | public int Height { get; set; } 13 | 14 | public Rectangle(Point position, int width, int height) 15 | { 16 | this.Position = position; 17 | this.Width = width; 18 | this.Height = height; 19 | } 20 | 21 | } 22 | // end::Rectangle[] 23 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch05/boardpanel/v3/BoardPanel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using Rectangle = eu.sig.training.ch05.boardpanel.v2.Rectangle; 4 | 5 | namespace eu.sig.training.ch05.boardpanel.v3 6 | { 7 | 8 | public class BoardPanel 9 | { 10 | /// 11 | /// Renders a single square on the given graphics context on the specified 12 | /// rectangle. 13 | /// 14 | /// The square to render. 15 | /// The graphics context to draw on. 16 | /// The position and dimension for rendering the square. 17 | // tag::render[] 18 | private void Render(Square square, Graphics g, Rectangle r) 19 | { 20 | Point position = r.Position; 21 | square.Sprite.Draw(g, r); 22 | foreach (Unit unit in square.Occupants) 23 | { 24 | unit.Sprite.Draw(g, r); 25 | } 26 | } 27 | // end::render[] 28 | 29 | private class Sprite 30 | { 31 | public void Draw(Graphics g, Rectangle r) 32 | { 33 | 34 | } 35 | } 36 | 37 | private class Unit 38 | { 39 | public Sprite Sprite { get; set; } 40 | } 41 | 42 | private class Square : Unit 43 | { 44 | 45 | public IList Occupants { get; set; } 46 | 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch05/buildandsendmail/v1/BuildAndSendMail.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch05.buildandsendmail.v1 2 | { 3 | public class BuildAndSendMail 4 | { 5 | // tag::buildAndSendMail[] 6 | public void DoBuildAndSendMail(MailMan m, string firstName, string lastName, 7 | string division, string subject, MailFont font, string message1, 8 | string message2, string message3) 9 | { 10 | // Format the email address 11 | string mId = $"{firstName[0]}.{lastName.Substring(0, 7)}" + 12 | $"@{division.Substring(0, 5)}.compa.ny"; 13 | // Format the message given the content type and raw message 14 | MailMessage mMessage = FormatMessage(font, 15 | message1 + message2 + message3); 16 | // Send message 17 | m.Send(mId, subject, mMessage); 18 | } 19 | // end::buildAndSendMail[] 20 | 21 | public MailMessage FormatMessage(MailFont font, string s) 22 | { 23 | return null; 24 | } 25 | 26 | public class MailMan 27 | { 28 | 29 | public void Send(string mId, string subject, MailMessage mMessage) { } 30 | 31 | } 32 | 33 | public class MailFont 34 | { 35 | 36 | } 37 | 38 | public class MailMessage 39 | { 40 | 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch05/buildandsendmail/v2/BuildAndSendMail.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace eu.sig.training.ch05.buildandsendmail.v2 3 | { 4 | public class BuildAndSendMail 5 | { 6 | 7 | // tag::buildAndSendMail[] 8 | public void DoBuildAndSendMail(MailMan m, MailAddress mAddress, 9 | MailBody mBody) 10 | { 11 | // Build the mail 12 | Mail mail = new Mail(mAddress, mBody); 13 | // Send the mail 14 | m.SendMail(mail); 15 | } 16 | 17 | public class Mail 18 | { 19 | public MailAddress Address { get; set; } 20 | public MailBody Body { get; set; } 21 | 22 | public Mail(MailAddress mAddress, MailBody mBody) 23 | { 24 | this.Address = mAddress; 25 | this.Body = mBody; 26 | } 27 | } 28 | 29 | public class MailBody 30 | { 31 | public string Subject { get; set; } 32 | public MailMessage Message { get; set; } 33 | 34 | public MailBody(string subject, MailMessage message) 35 | { 36 | this.Subject = subject; 37 | this.Message = message; 38 | } 39 | } 40 | 41 | public class MailAddress 42 | { 43 | public string MsgId { get; private set; } 44 | 45 | public MailAddress(string firstName, string lastName, 46 | string division) 47 | { 48 | this.MsgId = $"{firstName[0]}.{lastName.Substring(0, 7)}" + 49 | $"@{division.Substring(0, 5)}.compa.ny"; 50 | } 51 | } 52 | // end::buildAndSendMail[] 53 | 54 | public MailMessage FormatMessage(MailFont font, string s) 55 | { 56 | return null; 57 | } 58 | 59 | public class MailMan 60 | { 61 | public void Send(string mId, string subject, MailMessage mMessage) { } 62 | public void SendMail(Mail mail) { } 63 | } 64 | 65 | public class MailFont { } 66 | 67 | public class MailMessage { } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch05/chartlib/v1/Charts.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using Rectangle = eu.sig.training.ch05.boardpanel.v2.Rectangle; 3 | 4 | namespace eu.sig.training.ch05.chartlib.v1 5 | { 6 | public class Charts 7 | { 8 | // tag::drawBarChart[] 9 | public static void DrawBarChart(Graphics g, 10 | CategoryItemRendererState state, 11 | Rectangle graphArea, 12 | CategoryPlot plot, 13 | CategoryAxis domainAxis, 14 | ValueAxis rangeAxis, 15 | CategoryDataset dataset) 16 | { 17 | // .. 18 | } 19 | // end::drawBarChart[] 20 | 21 | // tag::drawBarChartDefault[] 22 | public static void DrawBarChart(Graphics g, CategoryDataset dataset) 23 | { 24 | Charts.DrawBarChart(g, 25 | CategoryItemRendererState.DEFAULT, 26 | new Rectangle(new Point(0, 0), 100, 100), 27 | CategoryPlot.DEFAULT, 28 | CategoryAxis.DEFAULT, 29 | ValueAxis.DEFAULT, 30 | dataset); 31 | } 32 | // end::drawBarChartDefault[] 33 | } 34 | 35 | public class CategoryItemRendererState 36 | { 37 | public const CategoryItemRendererState DEFAULT = null; 38 | } 39 | 40 | public class CategoryPlot 41 | { 42 | public const CategoryPlot DEFAULT = null; 43 | } 44 | 45 | public class CategoryAxis 46 | { 47 | public const CategoryAxis DEFAULT = null; 48 | } 49 | 50 | public class ValueAxis 51 | { 52 | public const ValueAxis DEFAULT = null; 53 | } 54 | 55 | public class CategoryDataset 56 | { 57 | public const CategoryDataset DEFAULT = null; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/advanceddigitalcamera/DigitalCamera.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace eu.sig.training.ch06.advanceddigitalcamera 4 | { 5 | 6 | // tag::DigitalCamera[] 7 | public class DigitalCamera 8 | { 9 | public Image TakeSnapshot() 10 | { 11 | // ... 12 | // end::DigitalCamera[] 13 | return Image.FromFile(""); 14 | // tag::DigitalCamera[] 15 | } 16 | 17 | public void FlashLightOn() 18 | { 19 | // ... 20 | } 21 | 22 | public void FlaslLightOff() 23 | { 24 | // ... 25 | } 26 | 27 | public Image TakePanoramaSnapshot() 28 | { 29 | // end::DigitalCamera[] 30 | return Image.FromFile(""); 31 | // tag::DigitalCamera[] 32 | // ... 33 | } 34 | 35 | public Video Record() 36 | { 37 | // ... 38 | // end::DigitalCamera[] 39 | return new Video(); 40 | // tag::DigitalCamera[] 41 | } 42 | 43 | public void SetTimer(int seconds) 44 | { 45 | // ... 46 | } 47 | 48 | public void ZoomIn() 49 | { 50 | // ... 51 | } 52 | 53 | public void ZoomOut() 54 | { 55 | // ... 56 | } 57 | } 58 | // end::DigitalCamera[] 59 | } 60 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/advanceddigitalcamera/Video.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.advanceddigitalcamera 2 | { 3 | 4 | public class Video 5 | { 6 | } 7 | 8 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/digitalcamera/DigitalCamera.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace eu.sig.training.ch06.digitalcamera 4 | { 5 | 6 | // tag::DigitalCamera[] 7 | public class DigitalCamera 8 | { 9 | public Image TakeSnapshot() 10 | { 11 | // ... 12 | // end::DigitalCamera[] 13 | return Image.FromFile(""); 14 | // tag::DigitalCamera[] 15 | } 16 | 17 | public void FlashLightOn() 18 | { 19 | // ... 20 | } 21 | 22 | public void FlashLightOff() 23 | { 24 | // ... 25 | } 26 | } 27 | // end::DigitalCamera[] 28 | } 29 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/digitalcamera/SmartphoneApp.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace eu.sig.training.ch06.digitalcamera 4 | { 5 | 6 | #pragma warning disable 219 7 | // tag::SmartphoneApp[] 8 | public class SmartphoneApp 9 | { 10 | private static DigitalCamera camera = new DigitalCamera(); 11 | 12 | public static void Main(string[] args) 13 | { 14 | // ... 15 | Image image = camera.TakeSnapshot(); 16 | // ... 17 | } 18 | } 19 | // end::SmartphoneApp[] 20 | #pragma warning restore 219 21 | } 22 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/simpledigitalcamera/DigitalCamera.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace eu.sig.training.ch06.simpledigitalcamera 4 | { 5 | 6 | // tag::DigitalCamera[] 7 | public class DigitalCamera : ISimpleDigitalCamera 8 | { 9 | // ... 10 | // end::DigitalCamera[] 11 | public Image TakeSnapshot() 12 | { 13 | return null; 14 | } 15 | 16 | public void FlashLightOn() 17 | { 18 | } 19 | 20 | public void FlashLightOff() 21 | { 22 | } 23 | // tag::DigitalCamera[] 24 | } 25 | // end::DigitalCamera[] 26 | } 27 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/simpledigitalcamera/ISimpleDigitalCamera.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace eu.sig.training.ch06.simpledigitalcamera 4 | { 5 | 6 | // tag::SimpleDigitalCamera[] 7 | public interface ISimpleDigitalCamera 8 | { 9 | Image TakeSnapshot(); 10 | 11 | void FlashLightOn(); 12 | 13 | void FlashLightOff(); 14 | } 15 | // end::SimpleDigitalCamera[] 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/simpledigitalcamera/SDK.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.simpledigitalcamera 2 | { 3 | 4 | public class SDK 5 | { 6 | public static ISimpleDigitalCamera GetCamera() 7 | { 8 | return new DigitalCamera(); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/simpledigitalcamera/SmartphoneApp.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace eu.sig.training.ch06.simpledigitalcamera 4 | { 5 | 6 | #pragma warning disable 219 7 | // tag::SmartphoneApp[] 8 | public class SmartphoneApp 9 | { 10 | private static ISimpleDigitalCamera camera = SDK.GetCamera(); 11 | 12 | public static void Main(string[] args) 13 | { 14 | // ... 15 | Image image = camera.TakeSnapshot(); 16 | // ... 17 | } 18 | } 19 | // end::SmartphoneApp[] 20 | #pragma warning restore 219 21 | } 22 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/NotificationType.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.userservice 2 | { 3 | 4 | public class NotificationType 5 | { 6 | public static NotificationType FromString(string type) 7 | { 8 | return new NotificationType(); 9 | } 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/User.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.userservice 2 | { 3 | 4 | public class User 5 | { 6 | public string Name { get; set; } 7 | 8 | public User() 9 | { 10 | Name = "user@example.com"; 11 | } 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.userservice 2 | { 3 | 4 | public class UserInfo 5 | { 6 | } 7 | 8 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/splitted/UserBlockService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace eu.sig.training.ch06.userservice.splitted 4 | { 5 | 6 | // tag::UserBlockService[] 7 | public class UserBlockService 8 | { 9 | public void BlockUser(User user) 10 | { 11 | // ... 12 | } 13 | 14 | public IList GetAllBlockedUsers() 15 | { 16 | // ... 17 | // end::UserBlockService[] 18 | return new List(); 19 | // tag::UserBlockService[] 20 | } 21 | } 22 | // end::UserBlockService[] 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/splitted/UserNotificationService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace eu.sig.training.ch06.userservice.splitted 4 | { 5 | 6 | // tag::UserNotificationService[] 7 | public class UserNotificationService 8 | { 9 | public IList GetNotificationTypes(User user) 10 | { 11 | // ... 12 | // end::UserNotificationService[] 13 | return new List(); 14 | // tag::UserNotificationService[] 15 | } 16 | 17 | public void Register(User user, NotificationType type) 18 | { 19 | // ... 20 | } 21 | 22 | public void Unregister(User user, NotificationType type) 23 | { 24 | // ... 25 | } 26 | } 27 | // end::UserNotificationService[] 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/splitted/UserService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace eu.sig.training.ch06.userservice.splitted 4 | { 5 | 6 | // tag::UserService[] 7 | public class UserService 8 | { 9 | public User LoadUser(string userId) 10 | { 11 | // ... 12 | // end::UserService[] 13 | return new User(); 14 | // tag::UserService[] 15 | } 16 | 17 | public bool DoesUserExist(string userId) 18 | { 19 | // ... 20 | // end::UserService[] 21 | return true; 22 | // tag::UserService[] 23 | } 24 | 25 | public User ChangeUserInfo(UserInfo userInfo) 26 | { 27 | // ... 28 | // end::UserService[] 29 | return new User(); 30 | // tag::UserService[] 31 | } 32 | 33 | public IList SearchUsers(UserInfo userInfo) 34 | { 35 | // ... 36 | // end::UserService[] 37 | return new List(); 38 | // tag::UserService[] 39 | } 40 | } 41 | // end::UserService[] 42 | } 43 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/v1/UserRestAPI.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.userservice.v1 2 | { 3 | 4 | // tag::UserRestAPI[] 5 | public class UserController : System.Web.Http.ApiController 6 | { 7 | 8 | private readonly UserService userService = new UserService(); 9 | 10 | // ... 11 | 12 | public System.Web.Http.IHttpActionResult GetUserById(string id) 13 | { 14 | User user = userService.LoadUser(id); 15 | if (user == null) 16 | { 17 | return NotFound(); 18 | } 19 | return Ok(user); 20 | } 21 | } 22 | // end::UserRestAPI[] 23 | } 24 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/v1/UserService.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.userservice.v1 2 | { 3 | 4 | // tag::UserService[] 5 | public class UserService 6 | { 7 | public User LoadUser(string userId) 8 | { 9 | // ... 10 | // end::UserService[] 11 | return new User(); 12 | // tag::UserService[] 13 | } 14 | 15 | public bool DoesUserExist(string userId) 16 | { 17 | // ... 18 | // end::UserService[] 19 | return true; 20 | // tag::UserService[] 21 | } 22 | 23 | public User ChangeUserInfo(UserInfo userInfo) 24 | { 25 | // ... 26 | // end::UserService[] 27 | return new User(); 28 | // tag::UserService[] 29 | } 30 | } 31 | // end::UserSerice[] 32 | } 33 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/v2/NotificationRestAPI.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch06.userservice.v2 2 | { 3 | 4 | // tag::NotificationRestAPI[] 5 | public class NotificationController : System.Web.Http.ApiController 6 | { 7 | private readonly UserService userService = new UserService(); 8 | 9 | // ... 10 | 11 | public System.Web.Http.IHttpActionResult Register(string id, 12 | string notificationType) 13 | { 14 | User user = userService.LoadUser(id); 15 | userService.RegisterForNotifications(user, 16 | NotificationType.FromString(notificationType)); 17 | return Ok(); 18 | } 19 | 20 | [System.Web.Http.HttpPost] 21 | [System.Web.Http.ActionName("unregister")] 22 | public System.Web.Http.IHttpActionResult Unregister(string id, 23 | string notificationType) 24 | { 25 | User user = userService.LoadUser(id); 26 | userService.UnregisterForNotifications(user, 27 | NotificationType.FromString(notificationType)); 28 | return Ok(); 29 | } 30 | } 31 | // end::NotificationRestAPI[] 32 | } 33 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/v2/UserService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace eu.sig.training.ch06.userservice.v2 4 | { 5 | 6 | // tag::UserService[] 7 | public class UserService 8 | { 9 | public User LoadUser(string userId) 10 | { 11 | // ... 12 | // end::UserService[] 13 | return new User(); 14 | // tag::UserService[] 15 | } 16 | 17 | public bool DoesUserExist(string userId) 18 | { 19 | // ... 20 | // end::UserService[] 21 | return true; 22 | // tag::UserService[] 23 | } 24 | 25 | public User ChangeUserInfo(UserInfo userInfo) 26 | { 27 | // ... 28 | // end::UserService[] 29 | return new User(); 30 | // tag::UserService[] 31 | } 32 | 33 | public List GetNotificationTypes(User user) 34 | { 35 | // ... 36 | // end::UserService[] 37 | return new List(); 38 | // tag::UserService[] 39 | } 40 | 41 | public void RegisterForNotifications(User user, NotificationType type) 42 | { 43 | // ... 44 | } 45 | 46 | public void UnregisterForNotifications(User user, NotificationType type) 47 | { 48 | // ... 49 | } 50 | } 51 | // end::UserSerice[] 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch06/userservice/v3/UserService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace eu.sig.training.ch06.userservice.v3 4 | { 5 | 6 | // tag::UserService[] 7 | public class UserService 8 | { 9 | public User LoadUser(string userId) 10 | { 11 | // ... 12 | // end::UserService[] 13 | return new User(); 14 | // tag::UserService[] 15 | } 16 | 17 | public bool DoesUserExist(string userId) 18 | { 19 | // ... 20 | // end::UserService[] 21 | return true; 22 | // tag::UserService[] 23 | } 24 | 25 | public User ChangeUserInfo(UserInfo userInfo) 26 | { 27 | // ... 28 | // end::UserService[] 29 | return new User(); 30 | // tag::UserService[] 31 | } 32 | 33 | public List GetNotificationTypes(User user) 34 | { 35 | // ... 36 | // end::UserService[] 37 | return new List(); 38 | // tag::UserService[] 39 | } 40 | 41 | public void RegisterForNotifications(User user, NotificationType type) 42 | { 43 | // ... 44 | } 45 | 46 | public void UnregisterForNotifications(User user, NotificationType type) 47 | { 48 | // ... 49 | } 50 | 51 | public List SearchUsers(UserInfo userInfo) 52 | { 53 | // ... 54 | // end::UserService[] 55 | return new List(); 56 | // tag::UserService[] 57 | } 58 | 59 | public void BlockUser(User user) 60 | { 61 | // ... 62 | } 63 | 64 | public List GetAllBlockedUsers() 65 | { 66 | // ... 67 | // end::UserService[] 68 | return new List(); 69 | // tag::UserService[] 70 | } 71 | } 72 | // end::UserSerice[] 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AWSCloudServerFactory.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | // tag::AWSCloudServerFactory[] 4 | public class AWSCloudServerFactory : ICloudServerFactory 5 | { 6 | public ICloudServer LaunchComputeServer() 7 | { 8 | return new AWSComputeServer(); 9 | } 10 | 11 | public ICloudServer LaunchDatabaseServer() 12 | { 13 | return new AWSDatabaseServer(); 14 | } 15 | 16 | public ICloudStorage CreateCloudStorage(long sizeGb) 17 | { 18 | return new AWSCloudStorage(sizeGb); 19 | } 20 | } 21 | // end::AWSCloudServerFactory[] 22 | } 23 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AWSCloudStorage.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public class AWSCloudStorage : ICloudStorage 4 | { 5 | public AWSCloudStorage(long sizeGb) 6 | { 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AWSComputeServer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public class AWSComputeServer : ICloudServer 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AWSDatabaseServer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public class AWSDatabaseServer : ICloudServer 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/ApplicationLauncher.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | // tag::ApplicationLauncher[] 4 | public class ApplicationLauncher 5 | { 6 | 7 | public static void Main(string[] args) 8 | { 9 | ICloudServerFactory factory; 10 | if (args[1].Equals("-azure")) 11 | { 12 | factory = new AzureCloudServerFactory(); 13 | } 14 | else 15 | { 16 | factory = new AWSCloudServerFactory(); 17 | } 18 | ICloudServer computeServer = factory.LaunchComputeServer(); 19 | ICloudServer databaseServer = factory.LaunchDatabaseServer(); 20 | // end::ApplicationLauncher[] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AzureCloudServerFactory.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 { 2 | // tag::AzureCloudServerFactory[] 3 | public class AzureCloudServerFactory : ICloudServerFactory { 4 | public ICloudServer LaunchComputeServer() { 5 | return new AzureComputeServer(); 6 | } 7 | 8 | public ICloudServer LaunchDatabaseServer() { 9 | return new AzureDatabaseServer(); 10 | } 11 | 12 | public ICloudStorage CreateCloudStorage(long sizeGb) { 13 | return new AzureCloudStorage(sizeGb); 14 | } 15 | } 16 | // end::AzureCloudServerFactory[] 17 | } 18 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AzureCloudStorage.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public class AzureCloudStorage : ICloudStorage 4 | { 5 | public AzureCloudStorage(long sizeGb) 6 | { 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AzureComputeServer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public class AzureComputeServer : ICloudServer 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/AzureDatabaseServer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public class AzureDatabaseServer : ICloudServer 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/ICloudServer.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public interface ICloudServer 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/ICloudServerFactory.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | // tag::CloudServerFactory[] 4 | public interface ICloudServerFactory 5 | { 6 | ICloudServer LaunchComputeServer(); 7 | 8 | ICloudServer LaunchDatabaseServer(); 9 | 10 | ICloudStorage CreateCloudStorage(long sizeGb); 11 | } 12 | // end::CloudServerFactory[] 13 | } 14 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch07/ICloudStorage.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch07 2 | { 3 | public interface ICloudStorage 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch10/PerfectPicture.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using eu.sig.training.ch06.simpledigitalcamera; 3 | 4 | namespace eu.sig.training.ch10 5 | { 6 | public class PerfectPicture 7 | { 8 | public static ISimpleDigitalCamera camera = null; 9 | 10 | // tag::takePerfectPicture[] 11 | public const int DAYLIGHT_START = 6; 12 | 13 | public Image TakePerfectPicture(int currentHour) 14 | { 15 | Image image; 16 | if (currentHour < PerfectPicture.DAYLIGHT_START) 17 | { 18 | camera.FlashLightOn(); 19 | image = camera.TakeSnapshot(); 20 | camera.FlashLightOff(); 21 | } 22 | else 23 | { 24 | image = camera.TakeSnapshot(); 25 | } 26 | return image; 27 | } 28 | // end::takePerfectPicture[] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch10/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using eu.sig.training.ch04.v1; 3 | 4 | namespace eu.sig.training.ch10 5 | { 6 | public class Program 7 | { 8 | [STAThread] 9 | public static void Main(string[] args) 10 | { 11 | string acct; 12 | do 13 | { 14 | Console.WriteLine("Type a bank account number on the next line."); 15 | acct = Console.ReadLine(); 16 | Console.WriteLine($"Bank account number '{acct}' is" + 17 | (Accounts.IsValid(acct) ? "" : " not") + " valid."); 18 | } while (!String.IsNullOrEmpty(acct)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch11/DeadCode.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch11 2 | { 3 | 4 | public class DeadCode 5 | { 6 | public class Transaction 7 | { 8 | public Transaction(long uid) 9 | { 10 | } 11 | } 12 | 13 | // tag::getTransaction[] 14 | public Transaction GetTransaction(long uid) 15 | { 16 | Transaction result = new Transaction(uid); 17 | if (result != null) 18 | { 19 | return result; 20 | } 21 | else 22 | { 23 | return LookupTransaction(uid); // <1> 24 | } 25 | } 26 | // end::getTransaction[] 27 | 28 | private Transaction LookupTransaction(long uid) 29 | { 30 | return null; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch11/MagicConstants.cs: -------------------------------------------------------------------------------- 1 | namespace eu.sig.training.ch11 2 | { 3 | public class MagicConstants 4 | { 5 | 6 | public class Customer 7 | { 8 | 9 | public Customer(int age) 10 | { 11 | this.Age = age; 12 | } 13 | 14 | public int Age { get; set; } 15 | } 16 | 17 | public class UseMagicConstants 18 | { 19 | 20 | // tag::calculateFareMagicConstants[] 21 | float CalculateFare(Customer c, long distance) 22 | { 23 | float travelledDistanceFare = distance * 0.10f; 24 | if (c.Age < 12) 25 | { 26 | travelledDistanceFare *= 0.25f; 27 | } 28 | else 29 | if (c.Age >= 65) 30 | { 31 | travelledDistanceFare *= 0.5f; 32 | } 33 | return 3.00f + travelledDistanceFare; 34 | } 35 | // end::calculateFareMagicConstants[] 36 | 37 | } 38 | 39 | public class DoNotUseMagicConstants 40 | { 41 | // tag::calculateFareDoNotUseMagicConstants[] 42 | private static readonly float BASE_RATE = 3.00f; 43 | private static readonly float FARE_PER_KM = 0.10f; 44 | private static readonly float DISCOUNT_RATE_CHILDREN = 0.25f; 45 | private static readonly float DISCOUNT_RATE_ELDERLY = 0.5f; 46 | private static readonly int MAXIMUM_AGE_CHILDREN = 12; 47 | private static readonly int MINIMUM_AGE_ELDERLY = 65; 48 | 49 | float CalculateFare(Customer c, long distance) 50 | { 51 | float travelledDistanceFare = distance * FARE_PER_KM; 52 | if (c.Age < MAXIMUM_AGE_CHILDREN) 53 | { 54 | travelledDistanceFare *= DISCOUNT_RATE_CHILDREN; 55 | } 56 | else 57 | if (c.Age >= MINIMUM_AGE_ELDERLY) 58 | { 59 | travelledDistanceFare *= DISCOUNT_RATE_ELDERLY; 60 | } 61 | return BASE_RATE + travelledDistanceFare; 62 | } 63 | // end::calculateFareDoNotUseMagicConstants[] 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/csharp/eu/sig/training/ch11/StandardContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eu.sig.training.ch11 { 4 | public class StandardContext { 5 | 6 | // tag::validateFilterMap[] 7 | private void ValidateFilterMap(FilterMap filterMap) { 8 | // Validate the proposed filter mapping 9 | string filterName = filterMap.GetFilterName(); 10 | string[] servletNames = filterMap.GetServletNames(); 11 | string[] urlPatterns = filterMap.GetURLPatterns(); 12 | if (FindFilterDef(filterName) == null) 13 | throw new Exception( 14 | sm.GetString("standardContext.filterMap.name", filterName)); 15 | 16 | if (!filterMap.GetMatchAllServletNames() && 17 | !filterMap.GetMatchAllUrlPatterns() && 18 | (servletNames.Length == 0) && (urlPatterns.Length == 0)) 19 | throw new Exception( 20 | sm.GetString("standardContext.filterMap.either")); 21 | // FIXME: Older spec revisions may still check this 22 | /* 23 | if ((servletNames.length != 0) && (urlPatterns.length != 0)) 24 | throw new IllegalArgumentException 25 | (sm.getString("standardContext.filterMap.either")); 26 | */ 27 | for (int i = 0; i < urlPatterns.Length; i++) { 28 | if (!ValidateURLPattern(urlPatterns[i])) { 29 | throw new Exception( 30 | sm.GetString("standardContext.filterMap.pattern", 31 | urlPatterns[i])); 32 | } 33 | } 34 | } 35 | // end::validateFilterMap[] 36 | 37 | public class GetStringObject { 38 | public string GetString(string s) { 39 | return s; 40 | } 41 | 42 | public string GetString(string s, object o) { 43 | return s; 44 | } 45 | } 46 | 47 | private GetStringObject sm = new GetStringObject(); 48 | 49 | public class FilterMap { 50 | 51 | public bool GetMatchAllUrlPatterns() { 52 | return false; 53 | } 54 | 55 | public string[] GetURLPatterns() { 56 | return null; 57 | } 58 | 59 | public string[] GetServletNames() { 60 | return null; 61 | } 62 | 63 | public string GetFilterName() { 64 | return null; 65 | } 66 | 67 | public bool GetMatchAllServletNames() { 68 | return false; 69 | } 70 | 71 | } 72 | 73 | private bool ValidateURLPattern(string s) { 74 | return false; 75 | } 76 | 77 | private object FindFilterDef(string filterName) { 78 | return null; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/csharp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch02/BalancesServlet.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch02; 2 | 3 | import java.io.IOException; 4 | import java.sql.Connection; 5 | import java.sql.DriverManager; 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.util.Properties; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServlet; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | public class BalancesServlet extends HttpServlet { 16 | private static final long serialVersionUID = 1L; 17 | private Properties conf; 18 | 19 | @Override 20 | // tag::doGet[] 21 | public void doGet(HttpServletRequest req, HttpServletResponse resp) 22 | throws ServletException, IOException { 23 | resp.setContentType("application/json"); 24 | try { 25 | Connection conn = DriverManager. 26 | getConnection(this.conf.getProperty("handler.jdbcurl")); 27 | ResultSet results = 28 | conn.createStatement() 29 | .executeQuery( 30 | "SELECT account, balance FROM ACCTS WHERE id=" 31 | + req.getParameter(conf. 32 | getProperty("request.parametername"))); 33 | float totalBalance = 0; 34 | resp.getWriter().print("{\"balances\":["); 35 | while (results.next()) { 36 | // Assuming result is 9-digit bank account number, 37 | // validate with 11-test: 38 | int sum = 0; 39 | for (int i = 0; i < results.getString("account") 40 | .length(); i++) { 41 | sum = sum + (9 - i) 42 | * Character.getNumericValue(results.getString( 43 | "account").charAt(i)); 44 | } 45 | if (sum % 11 == 0) { 46 | totalBalance += results.getFloat("balance"); 47 | resp.getWriter().print( 48 | "{\"" + results.getString("account") + "\":" 49 | + results.getFloat("balance") + "}"); 50 | } 51 | if (results.isLast()) { 52 | resp.getWriter().println("],"); 53 | } else { 54 | resp.getWriter().print(","); 55 | } 56 | } 57 | resp.getWriter().println("\"total\":" + totalBalance + "}"); 58 | } catch (SQLException e) { 59 | System.out.println("SQL exception: " + e.getMessage()); 60 | } 61 | } 62 | // end::doGet[] 63 | } 64 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch02/BoardFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch02; 2 | 3 | public class BoardFactory { 4 | // tag::createBoard[] 5 | public Board createBoard(Square[][] grid) { 6 | assert grid != null; 7 | 8 | Board board = new Board(grid); 9 | 10 | int width = board.getWidth(); 11 | int height = board.getHeight(); 12 | for (int x = 0; x < width; x++) { 13 | for (int y = 0; y < height; y++) { 14 | Square square = grid[x][y]; 15 | for (Direction dir : Direction.values()) { 16 | int dirX = (width + x + dir.getDeltaX()) % width; 17 | int dirY = (height + y + dir.getDeltaY()) % height; 18 | Square neighbour = grid[dirX][dirY]; 19 | square.link(neighbour, dir); 20 | } 21 | } 22 | } 23 | 24 | return board; 25 | } 26 | // end::createBoard[] 27 | } 28 | 29 | class Board { 30 | @SuppressWarnings("unused") 31 | public Board(Square[][] grid) {} 32 | 33 | public int getWidth() { 34 | return 0; 35 | } 36 | 37 | public int getHeight() { 38 | return 0; 39 | } 40 | } 41 | 42 | class Square { 43 | @SuppressWarnings("unused") 44 | public void link(Square neighbour, Direction dir) {} 45 | } 46 | 47 | class Direction { 48 | 49 | public static Direction[] values() { 50 | return null; 51 | } 52 | 53 | public int getDeltaY() { 54 | return 0; 55 | } 56 | 57 | public int getDeltaX() { 58 | return 0; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch02/Employees.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch02; 2 | 3 | public class Employees { 4 | // tag::printDepartmentEmployees[] 5 | public static void printDepartmentEmployees(String department) { 6 | Query q = new Query(); 7 | for (Employee e : q.addColumn("FamilyName") 8 | .addColumn("Initials") 9 | .addColumn("GivenName") 10 | .addColumn("AddressLine1") 11 | .addColumn("ZIPcode") 12 | .addColumn("City") 13 | .addTable("EMPLOYEES") 14 | .addWhere("EmployeeDep='" + department + "'") 15 | .execute()) { 16 | System.out.println("
" + e.getAddressLine1() 18 | + "
" + e.getZipCode() + e.getCity() + "
"); 19 | } 20 | } 21 | // end::printDepartmentEmployees[] 22 | } 23 | 24 | class Query { 25 | 26 | @SuppressWarnings("unused") 27 | public Query addColumn(String string) { 28 | return null; 29 | } 30 | 31 | public Employee[] execute() { 32 | return null; 33 | } 34 | 35 | @SuppressWarnings("unused") 36 | public Query addWhere(String string) { 37 | return null; 38 | } 39 | 40 | @SuppressWarnings("unused") 41 | public Query addTable(String string) { 42 | return null; 43 | } 44 | } 45 | 46 | class Employee { 47 | 48 | public String getFamilyName() { 49 | return null; 50 | } 51 | 52 | public String getAddressLine1() { 53 | return null; 54 | } 55 | 56 | public String getZipCode() { 57 | return null; 58 | } 59 | 60 | public String getCity() { 61 | return null; 62 | } 63 | 64 | public String getInitials() { 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch02/Level.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch02; 2 | 3 | import java.util.List; 4 | 5 | public class Level { 6 | private boolean inProgress; 7 | private final List observers; 8 | 9 | Level(List observers) { 10 | this.observers = observers; 11 | } 12 | 13 | // tag::start[] 14 | public void start() { 15 | if (inProgress) { 16 | return; 17 | } 18 | inProgress = true; 19 | // Update observers if player died: 20 | if (!isAnyPlayerAlive()) { 21 | for (LevelObserver o : observers) { 22 | o.levelLost(); 23 | } 24 | } 25 | // Update observers if all pellets eaten: 26 | if (remainingPellets() == 0) { 27 | for (LevelObserver o : observers) { 28 | o.levelWon(); 29 | } 30 | } 31 | } 32 | // end::start[] 33 | 34 | @SuppressWarnings("unused") 35 | // tag::updateObservers[] 36 | private void updateObservers() { 37 | // Update observers if player died: 38 | if (!isAnyPlayerAlive()) { 39 | for (LevelObserver o : observers) { 40 | o.levelLost(); 41 | } 42 | } 43 | // Update observers if all pellets eaten: 44 | if (remainingPellets() == 0) { 45 | for (LevelObserver o : observers) { 46 | o.levelWon(); 47 | } 48 | } 49 | } 50 | // end::updateObservers[] 51 | 52 | @SuppressWarnings("unused") 53 | // tag::updateObserversPlayerDied[] 54 | private void updateObserversPlayerDied() { 55 | if (!isAnyPlayerAlive()) { 56 | for (LevelObserver o : observers) { 57 | o.levelLost(); 58 | } 59 | } 60 | } 61 | 62 | // end::updateObserversPlayerDied[] 63 | 64 | @SuppressWarnings("unused") 65 | // tag::updateObserversPelletsEaten[] 66 | private void updateObserversPelletsEaten() { 67 | if (remainingPellets() == 0) { 68 | for (LevelObserver o : observers) { 69 | o.levelWon(); 70 | } 71 | } 72 | } 73 | // end::updateObserversPelletsEaten[] 74 | 75 | private int remainingPellets() { 76 | return 0; 77 | } 78 | 79 | private boolean isAnyPlayerAlive() { 80 | return false; 81 | } 82 | } 83 | 84 | class LevelObserver { 85 | public void levelLost() {} 86 | public void levelWon() {} 87 | } 88 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch02/LevelHelper.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch02; 2 | 3 | public class LevelHelper { 4 | private boolean inProgress; 5 | 6 | // tag::firstStepStart[] 7 | public void start() { 8 | if (inProgress) { 9 | return; 10 | } 11 | inProgress = true; 12 | } 13 | // end::firstStepStart[] 14 | } 15 | 16 | class ExtractMethod { 17 | private boolean inProgress; 18 | 19 | // tag::extractMethodStart[] 20 | public void start() { 21 | if (inProgress) { 22 | return; 23 | } 24 | inProgress = true; 25 | updateObservers(); 26 | } 27 | // end::extractMethodStart[] 28 | 29 | // tag::updateObservers[] 30 | private void updateObservers() { 31 | updateObserversPlayerDied(); 32 | updateObserversPelletsEaten(); 33 | } 34 | // end::updateObservers[] 35 | 36 | private void updateObserversPlayerDied() {} 37 | 38 | private void updateObserversPelletsEaten() {} 39 | } 40 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch02/v1/BoardFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch02.v1; 2 | 3 | public class BoardFactory { 4 | // tag::createBoard[] 5 | public Board createBoard(Square[][] grid) { 6 | assert grid != null; 7 | 8 | Board board = new Board(grid); 9 | 10 | int width = board.getWidth(); 11 | int height = board.getHeight(); 12 | for (int x = 0; x < width; x++) { 13 | for (int y = 0; y < height; y++) { 14 | Square square = grid[x][y]; 15 | for (Direction dir : Direction.values()) { 16 | setLink(square, dir, x, y, width, height, grid); 17 | } 18 | } 19 | } 20 | 21 | return board; 22 | } 23 | // end::createBoard[] 24 | 25 | // tag::setLink[] 26 | private void setLink(Square square, Direction dir, int x, int y, int width, 27 | int height, Square[][] grid) { 28 | int dirX = (width + x + dir.getDeltaX()) % width; 29 | int dirY = (height + y + dir.getDeltaY()) % height; 30 | Square neighbour = grid[dirX][dirY]; 31 | square.link(neighbour, dir); 32 | } 33 | // end::setLink[] 34 | } 35 | 36 | class Board { 37 | @SuppressWarnings("unused") 38 | public Board(Square[][] grid) {} 39 | 40 | public int getWidth() { 41 | return 0; 42 | } 43 | 44 | public int getHeight() { 45 | return 0; 46 | } 47 | } 48 | 49 | class Square { 50 | @SuppressWarnings("unused") 51 | public void link(Square neighbour, Direction dir) {} 52 | } 53 | 54 | class Direction { 55 | 56 | public static Direction[] values() { 57 | return null; 58 | } 59 | 60 | public int getDeltaY() { 61 | return 0; 62 | } 63 | 64 | public int getDeltaX() { 65 | return 0; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch02/v2/BoardFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch02.v2; 2 | 3 | public class BoardFactory { 4 | // tag::createBoard[] 5 | public Board createBoard(Square[][] grid) { 6 | return new BoardCreator(grid).create(); 7 | } 8 | // end::createBoard[] 9 | } 10 | 11 | // tag::BoardCreator[] 12 | class BoardCreator { 13 | private Square[][] grid; 14 | private Board board; 15 | private int width; 16 | private int height; 17 | 18 | BoardCreator(Square[][] grid) { 19 | assert grid != null; 20 | this.grid = grid; 21 | this.board = new Board(grid); 22 | this.width = board.getWidth(); 23 | this.height = board.getHeight(); 24 | } 25 | 26 | Board create() { 27 | for (int x = 0; x < width; x++) { 28 | for (int y = 0; y < height; y++) { 29 | Square square = grid[x][y]; 30 | for (Direction dir : Direction.values()) { 31 | setLink(square, dir, x, y); 32 | } 33 | } 34 | } 35 | return this.board; 36 | } 37 | 38 | private void setLink(Square square, Direction dir, int x, int y) { 39 | int dirX = (width + x + dir.getDeltaX()) % width; 40 | int dirY = (height + y + dir.getDeltaY()) % height; 41 | Square neighbour = grid[dirX][dirY]; 42 | square.link(neighbour, dir); 43 | } 44 | } 45 | 46 | // end::BoardCreator[] 47 | 48 | class Board { 49 | @SuppressWarnings("unused") 50 | public Board(Square[][] grid) {} 51 | 52 | public int getWidth() { 53 | return 0; 54 | } 55 | 56 | public int getHeight() { 57 | return 0; 58 | } 59 | } 60 | 61 | class Square { 62 | @SuppressWarnings("unused") 63 | public void link(Square neighbour, Direction dir) {} 64 | } 65 | 66 | class Direction { 67 | 68 | public static Direction[] values() { 69 | return null; 70 | } 71 | 72 | public int getDeltaY() { 73 | return 0; 74 | } 75 | 76 | public int getDeltaX() { 77 | return 0; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/Flag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class Flag { 8 | private final List colors; 9 | 10 | public Flag(Color... colors) { 11 | this.colors = Arrays.asList(colors); 12 | } 13 | 14 | public List getColors() { 15 | return colors; 16 | } 17 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/FlagFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class FlagFactory { 8 | 9 | // tag::getFlag[] 10 | public List getFlagColors(Nationality nationality) { 11 | List result; 12 | switch (nationality) { 13 | case DUTCH: 14 | result = Arrays.asList(Color.RED, Color.WHITE, Color.BLUE); 15 | break; 16 | case GERMAN: 17 | result = Arrays.asList(Color.BLACK, Color.RED, Color.YELLOW); 18 | break; 19 | case BELGIAN: 20 | result = Arrays.asList(Color.BLACK, Color.YELLOW, Color.RED); 21 | break; 22 | case FRENCH: 23 | result = Arrays.asList(Color.BLUE, Color.WHITE, Color.RED); 24 | break; 25 | case ITALIAN: 26 | result = Arrays.asList(Color.GREEN, Color.WHITE, Color.RED); 27 | break; 28 | case UNCLASSIFIED: 29 | default: 30 | result = Arrays.asList(Color.GRAY); 31 | break; 32 | } 33 | return result; 34 | } 35 | // end::getFlag[] 36 | 37 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/FlagFactoryOops.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | public class FlagFactoryOops { 7 | private static class Color extends java.awt.Color { 8 | private static final long serialVersionUID = 1L; 9 | public static Color BLACK = getColor(java.awt.Color.BLACK); 10 | public static Color BLUE = getColor(java.awt.Color.BLUE); 11 | public static Color RED = getColor(java.awt.Color.RED); 12 | public static Color GREEN = getColor(java.awt.Color.GREEN); 13 | public static Color GRAY = getColor(java.awt.Color.GRAY); 14 | public static Color LIGHT_BLUE = getColor(new java.awt.Color(0, 163, 224)); 15 | public static Color WHITE = getColor(java.awt.Color.WHITE); 16 | public static Color YELLOW = getColor(java.awt.Color.YELLOW); 17 | 18 | public Color(java.awt.Color realColor) { 19 | super(realColor.getRGB()); 20 | } 21 | 22 | public static Color getColor(java.awt.Color c) { 23 | return new Color(c); 24 | } 25 | } 26 | 27 | public List getFlagColors(Nationality nationality) { 28 | List result; 29 | switch (nationality) { 30 | // tag::getFlag[] 31 | case DUTCH: 32 | result = Arrays.asList(Color.RED, Color.WHITE, Color.BLUE); 33 | case LUXEMBOURGER: 34 | result = Arrays.asList(Color.RED, Color.WHITE, Color.LIGHT_BLUE); 35 | break; 36 | case GERMAN: 37 | // end::getFlag[] 38 | result = Arrays.asList(Color.BLACK, Color.RED, Color.YELLOW); 39 | break; 40 | case BELGIAN: 41 | result = Arrays.asList(Color.BLACK, Color.YELLOW, Color.RED); 42 | break; 43 | case FRENCH: 44 | result = Arrays.asList(Color.BLUE, Color.WHITE, Color.RED); 45 | break; 46 | case ITALIAN: 47 | result = Arrays.asList(Color.GREEN, Color.WHITE, Color.RED); 48 | break; 49 | case UNCLASSIFIED: 50 | default: 51 | result = Arrays.asList(Color.GRAY); 52 | break; 53 | } 54 | return result; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/FlagFactoryWithMap.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03; 2 | 3 | import static eu.sig.training.ch03.Nationality.BELGIAN; 4 | import static eu.sig.training.ch03.Nationality.DUTCH; 5 | import static eu.sig.training.ch03.Nationality.FRENCH; 6 | import static eu.sig.training.ch03.Nationality.GERMAN; 7 | import static eu.sig.training.ch03.Nationality.ITALIAN; 8 | 9 | import java.awt.Color; 10 | import java.util.Arrays; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | public class FlagFactoryWithMap { 16 | 17 | // tag::getFlag[] 18 | private static Map> FLAGS = 19 | new HashMap>(); 20 | 21 | static { 22 | FLAGS.put(DUTCH, Arrays.asList(Color.RED, Color.WHITE, Color.BLUE)); 23 | FLAGS.put(GERMAN, Arrays.asList(Color.BLACK, Color.RED, Color.YELLOW)); 24 | FLAGS.put(BELGIAN, Arrays.asList(Color.BLACK, Color.YELLOW, Color.RED)); 25 | FLAGS.put(FRENCH, Arrays.asList(Color.BLUE, Color.WHITE, Color.RED)); 26 | FLAGS.put(ITALIAN, Arrays.asList(Color.GREEN, Color.WHITE, Color.RED)); 27 | } 28 | 29 | public List getFlagColors(Nationality nationality) { 30 | List colors = FLAGS.get(nationality); 31 | return colors != null ? colors : Arrays.asList(Color.GRAY); 32 | } 33 | // end::getFlag[] 34 | 35 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/Nationality.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03; 2 | 3 | public enum Nationality { 4 | DUTCH, GERMAN, BELGIAN, LUXEMBOURGER, FRENCH, ITALIAN, UNCLASSIFIED 5 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/binarytree/BinaryTreeNode.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.binarytree; 2 | 3 | public class BinaryTreeNode> { 4 | private final T value; 5 | private BinaryTreeNode left; 6 | private BinaryTreeNode right; 7 | 8 | public BinaryTreeNode(T value) { 9 | this.value = value; 10 | } 11 | 12 | public void insert(T value) { 13 | if (value.compareTo(this.value) < 0) { 14 | if (left != null) { 15 | left.insert(value); 16 | } else { 17 | left = new BinaryTreeNode(value); 18 | } 19 | } else { 20 | if (right != null) { 21 | right.insert(value); 22 | } else { 23 | right = new BinaryTreeNode(value); 24 | } 25 | } 26 | } 27 | 28 | public BinaryTreeNode getLeft() { 29 | return left; 30 | } 31 | 32 | public BinaryTreeNode getRight() { 33 | return right; 34 | } 35 | 36 | public T getValue() { 37 | return value; 38 | } 39 | 40 | public boolean isLeaf() { 41 | return left == null && right == null; 42 | } 43 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/binarytree/TreeException.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.binarytree; 2 | 3 | @SuppressWarnings("serial") 4 | public class TreeException extends RuntimeException { 5 | public TreeException(String msg) { 6 | super(msg); 7 | } 8 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/binarytree/v1/BinaryTreeSearch.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.binarytree.v1; 2 | 3 | import eu.sig.training.ch03.binarytree.TreeException; 4 | import eu.sig.training.ch03.binarytree.BinaryTreeNode; 5 | 6 | public class BinaryTreeSearch { 7 | 8 | // tag::calculateDepth[] 9 | public static int calculateDepth(BinaryTreeNode t, int n) { 10 | int depth = 0; 11 | if (t.getValue() == n) { 12 | return depth; 13 | } else { 14 | if (n < t.getValue()) { 15 | BinaryTreeNode left = t.getLeft(); 16 | if (left == null) { 17 | throw new TreeException("Value not found in tree!"); 18 | } else { 19 | return 1 + calculateDepth(left, n); 20 | } 21 | } else { 22 | BinaryTreeNode right = t.getRight(); 23 | if (right == null) { 24 | throw new TreeException("Value not found in tree!"); 25 | } else { 26 | return 1 + calculateDepth(right, n); 27 | } 28 | } 29 | } 30 | } 31 | // end::calculateDepth[] 32 | } 33 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/binarytree/v2/BinaryTreeSearch.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.binarytree.v2; 2 | 3 | import eu.sig.training.ch03.binarytree.BinaryTreeNode; 4 | import eu.sig.training.ch03.binarytree.TreeException; 5 | 6 | public class BinaryTreeSearch { 7 | 8 | // tag::calculateDepth[] 9 | public static int calculateDepth(BinaryTreeNode t, int n) { 10 | int depth = 0; 11 | if (t.getValue() == n) 12 | return depth; 13 | if (n < t.getValue() && t.getLeft() != null) 14 | return 1 + calculateDepth(t.getLeft(), n); 15 | if (n > t.getValue() && t.getRight() != null) 16 | return 1 + calculateDepth(t.getRight(), n); 17 | throw new TreeException("Value not found in tree!"); 18 | } 19 | // end::calculateDepth[] 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/binarytree/v3/BinaryTreeSearch.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.binarytree.v3; 2 | 3 | import eu.sig.training.ch03.binarytree.BinaryTreeNode; 4 | import eu.sig.training.ch03.binarytree.TreeException; 5 | 6 | public class BinaryTreeSearch { 7 | 8 | // tag::calculateDepth[] 9 | public static int calculateDepth(BinaryTreeNode t, int n) { 10 | int depth = 0; 11 | if (t.getValue() == n) 12 | return depth; 13 | else 14 | return traverseByValue(t, n); 15 | } 16 | 17 | private static int traverseByValue(BinaryTreeNode t, int n) { 18 | BinaryTreeNode childNode = getChildNode(t, n); 19 | if (childNode == null) { 20 | throw new TreeException("Value not found in tree!"); 21 | } else { 22 | return 1 + calculateDepth(childNode, n); 23 | } 24 | } 25 | 26 | private static BinaryTreeNode getChildNode( 27 | BinaryTreeNode t, int n) { 28 | if (n < t.getValue()) { 29 | return t.getLeft(); 30 | } else { 31 | return t.getRight(); 32 | } 33 | } 34 | // end::calculateDepth[] 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/BelgianFlag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class BelgianFlag implements Flag { 8 | public List getColors() { 9 | return Arrays.asList(Color.BLACK, Color.RED, Color.YELLOW); 10 | } 11 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/DefaultFlag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class DefaultFlag implements Flag { 8 | public List getColors() { 9 | return Arrays.asList(Color.GRAY); 10 | } 11 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/DutchFlag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | // tag::DutchFlag[] 8 | public class DutchFlag implements Flag { 9 | public List getColors() { 10 | return Arrays.asList(Color.RED, Color.WHITE, Color.BLUE); 11 | } 12 | } 13 | // end::DutchFlag[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/Flag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import java.awt.Color; 4 | import java.util.List; 5 | 6 | // tag::Flag[] 7 | public interface Flag { 8 | List getColors(); 9 | } 10 | // end::Flag[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/FlagFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import static eu.sig.training.ch03.Nationality.BELGIAN; 4 | import static eu.sig.training.ch03.Nationality.DUTCH; 5 | import static eu.sig.training.ch03.Nationality.FRENCH; 6 | import static eu.sig.training.ch03.Nationality.GERMAN; 7 | import static eu.sig.training.ch03.Nationality.ITALIAN; 8 | 9 | import java.awt.Color; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import eu.sig.training.ch03.Nationality; 15 | 16 | public class FlagFactory { 17 | 18 | // tag::getFlag[] 19 | private static final Map FLAGS = 20 | new HashMap(); 21 | 22 | static { 23 | FLAGS.put(DUTCH, new DutchFlag()); 24 | FLAGS.put(GERMAN, new GermanFlag()); 25 | FLAGS.put(BELGIAN, new BelgianFlag()); 26 | FLAGS.put(FRENCH, new FrenchFlag()); 27 | FLAGS.put(ITALIAN, new ItalianFlag()); 28 | } 29 | 30 | public List getFlagColors(Nationality nationality) { 31 | Flag flag = FLAGS.get(nationality); 32 | flag = flag != null ? flag : new DefaultFlag(); 33 | return flag.getColors(); 34 | } 35 | // end::getFlag[] 36 | 37 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/FrenchFlag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | 8 | public class FrenchFlag implements Flag { 9 | public List getColors() { 10 | return Arrays.asList(Color.BLUE, Color.WHITE, Color.RED); 11 | } 12 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/GermanFlag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class GermanFlag implements Flag { 8 | public List getColors() { 9 | return Arrays.asList(Color.BLACK, Color.RED, Color.YELLOW); 10 | } 11 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch03/withmapandtypes/ItalianFlag.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.withmapandtypes; 2 | 3 | import java.awt.Color; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | // tag::ItalianFlag[] 8 | public class ItalianFlag implements Flag { 9 | public List getColors() { 10 | return Arrays.asList(Color.GREEN, Color.WHITE, Color.RED); 11 | } 12 | } 13 | // end::ItalianFlag[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/BusinessException.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04; 2 | 3 | public class BusinessException extends Exception { 4 | private static final long serialVersionUID = 1L; 5 | 6 | public BusinessException(String message) { 7 | super(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/Clones.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04; 2 | 3 | public class Clones { 4 | private String givenName; 5 | private String familyName; 6 | private float pageWidthInCm; 7 | 8 | // tag::one-six-line-clone[] 9 | public void setGivenName(String givenName) { 10 | this.givenName = givenName; 11 | } 12 | 13 | public void setFamilyName(String familyName) { 14 | this.familyName = familyName; 15 | } 16 | // end::one-six-line-clone[] 17 | 18 | public String getGivenName() { 19 | return givenName; 20 | } 21 | 22 | public String getFamilyName() { 23 | return familyName; 24 | } 25 | 26 | // tag::type-2-clone[] 27 | public void setPageWidthInInches(float newWidth) { 28 | float cmPerInch = 2.54f; 29 | this.pageWidthInCm = newWidth * cmPerInch; 30 | // A few more lines. 31 | } 32 | 33 | public void setPageWidthInPoints(float newWidth) { 34 | float cmPerPoint = 0.0352777f; 35 | this.pageWidthInCm = newWidth * cmPerPoint; 36 | // A few more lines (same as in setPageWidthInInches). 37 | } 38 | // end::type-2-clone[] 39 | 40 | public float getPageWidthInCm() { 41 | return pageWidthInCm; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/Money.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04; 2 | 3 | public class Money { 4 | @SuppressWarnings("unused") 5 | public boolean greaterThan(int limit) { 6 | return true; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v1/Accounts.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v1; 2 | 3 | public class Accounts { 4 | @SuppressWarnings("unused") 5 | public static CheckingAccount findAcctByNumber(String number) { 6 | return new CheckingAccount(); 7 | } 8 | 9 | // tag::isValid[] 10 | public static boolean isValid(String number) { 11 | int sum = 0; 12 | for (int i = 0; i < number.length(); i++) { 13 | sum = sum + (9 - i) * Character.getNumericValue(number.charAt(i)); 14 | } 15 | return sum % 11 == 0; 16 | } 17 | // end::isValid[] 18 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v1/CheckingAccount.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v1; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | 6 | // tag::CheckingAccount[] 7 | public class CheckingAccount { 8 | private int transferLimit = 100; 9 | 10 | public Transfer makeTransfer(String counterAccount, Money amount) 11 | throws BusinessException { 12 | // 1. Check withdrawal limit: 13 | if (amount.greaterThan(this.transferLimit)) { 14 | throw new BusinessException("Limit exceeded!"); 15 | } 16 | // 2. Assuming result is 9-digit bank account number, validate 11-test: 17 | int sum = 0; 18 | for (int i = 0; i < counterAccount.length(); i++) { 19 | sum = sum + (9-i) * Character.getNumericValue( 20 | counterAccount.charAt(i)); 21 | } 22 | if (sum % 11 == 0) { 23 | // 3. Look up counter account and make transfer object: 24 | CheckingAccount acct = Accounts.findAcctByNumber(counterAccount); 25 | Transfer result = new Transfer(this, acct, amount); 26 | return result; 27 | } else { 28 | throw new BusinessException("Invalid account number!"); 29 | } 30 | } 31 | } 32 | // end::CheckingAccount[] 33 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v1/SavingsAccount.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v1; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | 6 | // tag::SavingsAccount[] 7 | public class SavingsAccount { 8 | CheckingAccount registeredCounterAccount; 9 | 10 | public Transfer makeTransfer(String counterAccount, Money amount) 11 | throws BusinessException { 12 | // 1. Assuming result is 9-digit bank account number, validate 11-test: 13 | int sum = 0; // <1> 14 | for (int i = 0; i < counterAccount.length(); i++) { 15 | sum = sum + (9 - i) * Character.getNumericValue( 16 | counterAccount.charAt(i)); 17 | } 18 | if (sum % 11 == 0) { 19 | // 2. Look up counter account and make transfer object: 20 | CheckingAccount acct = Accounts.findAcctByNumber(counterAccount); 21 | Transfer result = new Transfer(this, acct, amount); // <2> 22 | // 3. Check whether withdrawal is to registered counter account: 23 | if (result.getCounterAccount().equals(this.registeredCounterAccount)) 24 | { 25 | return result; 26 | } else { 27 | throw new BusinessException("Counter-account not registered!"); 28 | } 29 | } else { 30 | throw new BusinessException("Invalid account number!!"); 31 | } 32 | } 33 | } 34 | // end::SavingsAccount[] 35 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v1/Transfer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v1; 2 | 3 | import eu.sig.training.ch04.Money; 4 | 5 | public class Transfer { 6 | CheckingAccount counterAccount; 7 | 8 | @SuppressWarnings("unused") 9 | public Transfer(CheckingAccount acct1, CheckingAccount acct2, Money m) {} 10 | 11 | @SuppressWarnings("unused") 12 | public Transfer(SavingsAccount acct1, CheckingAccount acct2, Money m) {} 13 | 14 | public CheckingAccount getCounterAccount() { 15 | return this.counterAccount; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v2/Accounts.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v2; 2 | 3 | public class Accounts { 4 | @SuppressWarnings("unused") 5 | public static CheckingAccount findAcctByNumber(String number) { 6 | return new CheckingAccount(); 7 | } 8 | 9 | // tag::isValid[] 10 | public static boolean isValid(String number) { 11 | int sum = 0; 12 | for (int i = 0; i < number.length(); i++) { 13 | sum = sum + (9 - i) * Character.getNumericValue(number.charAt(i)); 14 | } 15 | return sum % 11 == 0; 16 | } 17 | // end::isValid[] 18 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v2/CheckingAccount.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v2; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | 6 | // tag::CheckingAccount[] 7 | public class CheckingAccount { 8 | private int transferLimit = 100; 9 | 10 | public Transfer makeTransfer(String counterAccount, Money amount) 11 | throws BusinessException { 12 | // 1. Check withdrawal limit: 13 | if (amount.greaterThan(this.transferLimit)) { 14 | throw new BusinessException("Limit exceeded!"); 15 | } 16 | if (Accounts.isValid(counterAccount)) { // <1> 17 | // 2. Look up counter account and make transfer object: 18 | CheckingAccount acct = Accounts.findAcctByNumber(counterAccount); 19 | Transfer result = new Transfer(this, acct, amount); // <2> 20 | return result; 21 | } else { 22 | throw new BusinessException("Invalid account number!"); 23 | } 24 | } 25 | 26 | } 27 | // end::CheckingAccount[] 28 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v2/SavingsAccount.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v2; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | 6 | // tag::SavingsAccount[] 7 | public class SavingsAccount { 8 | CheckingAccount registeredCounterAccount; 9 | 10 | public Transfer makeTransfer(String counterAccount, Money amount) 11 | throws BusinessException { 12 | // 1. Assuming result is 9-digit bank account number, 13 | // validate with 11-test: 14 | if (Accounts.isValid(counterAccount)) { // <1> 15 | // 2. Look up counter account and make transfer object: 16 | CheckingAccount acct = Accounts.findAcctByNumber(counterAccount); 17 | Transfer result = new Transfer(this, acct, amount); // <2> 18 | if (result.getCounterAccount().equals(this.registeredCounterAccount)) 19 | { 20 | return result; 21 | } else { 22 | throw new BusinessException("Counter-account not registered!"); 23 | } 24 | } else { 25 | throw new BusinessException("Invalid account number!!"); 26 | } 27 | } 28 | 29 | } 30 | // end::SavingsAccount[] 31 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v2/Transfer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v2; 2 | 3 | import eu.sig.training.ch04.Money; 4 | 5 | public class Transfer { 6 | CheckingAccount counterAccount; 7 | 8 | @SuppressWarnings("unused") 9 | public Transfer(CheckingAccount acct1, CheckingAccount acct2, Money m) {} 10 | 11 | @SuppressWarnings("unused") 12 | public Transfer(SavingsAccount acct1, CheckingAccount acct2, Money m) {} 13 | 14 | public CheckingAccount getCounterAccount() { 15 | return this.counterAccount; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v3/Account.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v3; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | 6 | // tag::Account[] 7 | public class Account { 8 | public Transfer makeTransfer(String counterAccount, Money amount) 9 | throws BusinessException { 10 | // 1. Assuming result is 9-digit bank account number, validate 11-test: 11 | int sum = 0; // <1> 12 | for (int i = 0; i < counterAccount.length(); i++) { 13 | sum = sum + (9 - i) * Character. 14 | getNumericValue(counterAccount.charAt(i)); 15 | } 16 | if (sum % 11 == 0) { 17 | // 2. Look up counter account and make transfer object: 18 | CheckingAccount acct = Accounts.findAcctByNumber(counterAccount); 19 | Transfer result = new Transfer(this, acct, amount); // <2> 20 | return result; 21 | } else { 22 | throw new BusinessException("Invalid account number!"); 23 | } 24 | } 25 | } 26 | // end::Account[] 27 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v3/Accounts.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v3; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import eu.sig.training.ch04.BusinessException; 7 | 8 | public class Accounts { 9 | 10 | // The Java version of the Account class does not have a string Number as property, 11 | // and the Java edition of the book is already in print. So we add an external 12 | // association of Accounts and their numbers. 13 | public static Map ACCOUNTS = new HashMap(); 14 | public static Map NUMBERS = new HashMap(); 15 | 16 | // @SuppressWarnings("unused") 17 | public static CheckingAccount findAcctByNumber(String number) 18 | throws BusinessException { 19 | Object myAccount = ACCOUNTS.get(number); 20 | if (myAccount instanceof CheckingAccount) { 21 | return (CheckingAccount)myAccount; 22 | } else { 23 | throw new BusinessException("Not a checking account."); 24 | } 25 | } 26 | 27 | public static T makeAccount(Class clazz, 28 | String number) { 29 | try { 30 | T myAccount = clazz.newInstance(); 31 | ACCOUNTS.put(number, myAccount); 32 | NUMBERS.put(myAccount, number); 33 | return myAccount; 34 | } catch (Exception e) { 35 | System.exit(1); 36 | return null; 37 | } 38 | } 39 | 40 | public static String getAccountNumber(Account acct) { 41 | return NUMBERS.get(acct); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v3/CheckingAccount.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v3; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | 6 | // tag::CheckingAccount[] 7 | public class CheckingAccount extends Account { 8 | private int transferLimit = 100; 9 | 10 | @Override 11 | public Transfer makeTransfer(String counterAccount, Money amount) 12 | throws BusinessException { 13 | if (amount.greaterThan(this.transferLimit)) { 14 | throw new BusinessException("Limit exceeded!"); 15 | } 16 | return super.makeTransfer(counterAccount, amount); 17 | } 18 | } 19 | // end::CheckingAccount[] 20 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v3/SavingsAccount.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v3; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | 6 | // tag::SavingsAccount[] 7 | public class SavingsAccount extends Account { 8 | CheckingAccount registeredCounterAccount; 9 | 10 | @Override 11 | public Transfer makeTransfer(String counterAccount, Money amount) 12 | throws BusinessException { 13 | Transfer result = super.makeTransfer(counterAccount, amount); 14 | if (result.getCounterAccount().equals(this.registeredCounterAccount)) { 15 | return result; 16 | } else { 17 | throw new BusinessException("Counter-account not registered!"); 18 | } 19 | } 20 | } 21 | // end::SavingsAccount[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v3/Transfer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v3; 2 | 3 | import eu.sig.training.ch04.Money; 4 | 5 | public class Transfer { 6 | CheckingAccount counterAccount; 7 | 8 | @SuppressWarnings("unused") 9 | public Transfer(Account acct1, CheckingAccount acct2, Money m) { 10 | this.counterAccount = acct2; 11 | } 12 | 13 | public CheckingAccount getCounterAccount() { 14 | return this.counterAccount; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v4/Account.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v4; 2 | 3 | import eu.sig.training.ch04.BusinessException; 4 | import eu.sig.training.ch04.Money; 5 | import eu.sig.training.ch04.v3.CheckingAccount; 6 | 7 | // tag::Account[] 8 | public class Account { 9 | public Transfer makeTransfer(String counterAccount, Money amount) 10 | throws BusinessException { 11 | if (isValid(counterAccount)) { 12 | CheckingAccount acct = Accounts.findAcctByNumber(counterAccount); 13 | return new Transfer(this, acct, amount); 14 | } else { 15 | throw new BusinessException("Invalid account number!"); 16 | } 17 | } 18 | 19 | public static boolean isValid(String number) { 20 | int sum = 0; 21 | for (int i = 0; i < number.length(); i++) { 22 | sum = sum + (9 - i) * Character.getNumericValue(number.charAt(i)); 23 | } 24 | return sum % 11 == 0; 25 | } 26 | } 27 | // end::Account[] 28 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v4/Accounts.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v4; 2 | 3 | import eu.sig.training.ch04.v3.CheckingAccount; 4 | 5 | public class Accounts { 6 | @SuppressWarnings("unused") 7 | public static CheckingAccount findAcctByNumber(String number) { 8 | return new CheckingAccount(); 9 | } 10 | 11 | // Version that should make tests succeed (not used in book): 12 | public static boolean isValid(String number) { 13 | if (number.length() != 9) { 14 | return false; 15 | } 16 | int sum = 0; 17 | for (int i = 0; i < number.length(); i++) { 18 | if (!Character.isDigit(number.charAt(i))) { 19 | return false; 20 | } 21 | sum = sum + (9 - i) * Character.getNumericValue(number.charAt(i)); 22 | } 23 | return sum % 11 == 0; 24 | } 25 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch04/v4/Transfer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v4; 2 | 3 | import eu.sig.training.ch04.Money; 4 | import eu.sig.training.ch04.v3.CheckingAccount; 5 | 6 | public class Transfer { 7 | CheckingAccount counterAccount; 8 | 9 | @SuppressWarnings("unused") 10 | public Transfer(Account acct1, CheckingAccount acct2, Money m) {} 11 | 12 | public CheckingAccount getCounterAccount() { 13 | return this.counterAccount; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/boardpanel/v1/BoardPanel.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.boardpanel.v1; 2 | 3 | import java.awt.Graphics; 4 | import java.util.List; 5 | 6 | public class BoardPanel { 7 | @SuppressWarnings("unused") 8 | // tag::render[] 9 | /** 10 | * Renders a single square on the given graphics context on the specified 11 | * rectangle. 12 | * 13 | * @param square 14 | * The square to render. 15 | * @param g 16 | * The graphics context to draw on. 17 | * @param x 18 | * The x position to start drawing. 19 | * @param y 20 | * The y position to start drawing. 21 | * @param w 22 | * The width of this square (in pixels). 23 | * @param h 24 | * The height of this square (in pixels). 25 | */ 26 | private void render(Square square, Graphics g, int x, int y, int w, int h) { 27 | square.getSprite().draw(g, x, y, w, h); 28 | for (Unit unit : square.getOccupants()) { 29 | unit.getSprite().draw(g, x, y, w, h); 30 | } 31 | } 32 | // end::render[] 33 | 34 | private class Sprite { 35 | @SuppressWarnings("unused") 36 | public void draw(Graphics g, int x, int y, int w, int h) { 37 | 38 | } 39 | } 40 | 41 | private class Unit { 42 | public Sprite getSprite() { 43 | return null; 44 | } 45 | } 46 | 47 | private class Square extends Unit { 48 | 49 | public List getOccupants() { 50 | return null; 51 | } 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/boardpanel/v2/BoardPanel.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.boardpanel.v2; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.Point; 5 | import java.util.List; 6 | 7 | public class BoardPanel { 8 | @SuppressWarnings("unused") 9 | // tag::render[] 10 | /** 11 | * Renders a single square on the given graphics context on the specified 12 | * rectangle. 13 | * 14 | * @param square 15 | * The square to render. 16 | * @param g 17 | * The graphics context to draw on. 18 | * @param r 19 | * The position and dimension for rendering the square. 20 | */ 21 | private void render(Square square, Graphics g, Rectangle r) { 22 | Point position = r.getPosition(); 23 | square.getSprite().draw(g, position.x, position.y, r.getWidth(), 24 | r.getHeight()); 25 | for (Unit unit : square.getOccupants()) { 26 | unit.getSprite().draw(g, position.x, position.y, r.getWidth(), 27 | r.getHeight()); 28 | } 29 | } 30 | // end::render[] 31 | 32 | private class Sprite { 33 | @SuppressWarnings("unused") 34 | public void draw(Graphics g, int x, int y, int w, int h) { 35 | 36 | } 37 | } 38 | 39 | private class Unit { 40 | public Sprite getSprite() { 41 | return null; 42 | } 43 | } 44 | 45 | private class Square extends Unit { 46 | 47 | public List getOccupants() { 48 | return null; 49 | } 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/boardpanel/v2/Rectangle.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.boardpanel.v2; 2 | 3 | import java.awt.Point; 4 | 5 | // tag::Rectangle[] 6 | public class Rectangle { 7 | private final Point position; 8 | private final int width; 9 | private final int height; 10 | 11 | public Rectangle(Point position, int width, int height) { 12 | this.position = position; 13 | this.width = width; 14 | this.height = height; 15 | } 16 | 17 | public Point getPosition() { 18 | return position; 19 | } 20 | 21 | public int getWidth() { 22 | return width; 23 | } 24 | 25 | public int getHeight() { 26 | return height; 27 | } 28 | } 29 | // end::Rectangle[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/boardpanel/v3/BoardPanel.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.boardpanel.v3; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.Point; 5 | import java.util.List; 6 | 7 | import eu.sig.training.ch05.boardpanel.v2.Rectangle; 8 | 9 | public class BoardPanel { 10 | @SuppressWarnings("unused") 11 | /** 12 | * Renders a single square on the given graphics context on the specified 13 | * rectangle. 14 | * 15 | * @param square 16 | * The square to render. 17 | * @param g 18 | * The graphics context to draw on. 19 | * @param r 20 | * The position and dimension for rendering the square. 21 | */ 22 | // tag::render[] 23 | private void render(Square square, Graphics g, Rectangle r) { 24 | Point position = r.getPosition(); 25 | square.getSprite().draw(g, r); 26 | for (Unit unit : square.getOccupants()) { 27 | unit.getSprite().draw(g, r); 28 | } 29 | } 30 | // end::render[] 31 | 32 | private class Sprite { 33 | @SuppressWarnings("unused") 34 | public void draw(Graphics g, Rectangle r) { 35 | 36 | } 37 | } 38 | 39 | private class Unit { 40 | public Sprite getSprite() { 41 | return null; 42 | } 43 | } 44 | 45 | private class Square extends Unit { 46 | 47 | public List getOccupants() { 48 | return null; 49 | } 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/buildandsendmail/v1/BuildAndSendMail.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.buildandsendmail.v1; 2 | 3 | public class BuildAndSendMail { 4 | // tag::buildAndSendMail[] 5 | public void buildAndSendMail(MailMan m, String firstName, String lastName, 6 | String division, String subject, MailFont font, String message1, 7 | String message2, String message3) { 8 | // Format the email address 9 | String mId = firstName.charAt(0) + "." + lastName.substring(0, 7) + "@" 10 | + division.substring(0, 5) + ".compa.ny"; 11 | // Format the message given the content type and raw message 12 | MailMessage mMessage = formatMessage(font, 13 | message1 + message2 + message3); 14 | // Send message 15 | m.send(mId, subject, mMessage); 16 | } 17 | // end::buildAndSendMail[] 18 | 19 | @SuppressWarnings("unused") 20 | private MailMessage formatMessage(MailFont font, String string) { 21 | return null; 22 | } 23 | 24 | private class MailMan { 25 | 26 | @SuppressWarnings("unused") 27 | public void send(String mId, String subject, MailMessage mMessage) {} 28 | 29 | } 30 | 31 | private class MailFont { 32 | 33 | } 34 | 35 | private class MailMessage { 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/buildandsendmail/v2/BuildAndSendMail.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.buildandsendmail.v2; 2 | 3 | @SuppressWarnings("unused") 4 | public class BuildAndSendMail { 5 | 6 | // tag::buildAndSendMail[] 7 | public void buildAndSendMail(MailMan m, MailAddress mAddress, 8 | MailBody mBody) { 9 | // Build the mail 10 | Mail mail = new Mail(mAddress, mBody); 11 | // Send the mail 12 | m.sendMail(mail); 13 | } 14 | 15 | private class Mail { 16 | private MailAddress address; 17 | private MailBody body; 18 | 19 | private Mail(MailAddress mAddress, MailBody mBody) { 20 | this.address = mAddress; 21 | this.body = mBody; 22 | } 23 | } 24 | 25 | private class MailBody { 26 | String subject; 27 | MailMessage message; 28 | 29 | public MailBody(String subject, MailMessage message) { 30 | this.subject = subject; 31 | this.message = message; 32 | } 33 | } 34 | 35 | private class MailAddress { 36 | private String mId; 37 | 38 | private MailAddress(String firstName, String lastName, 39 | String division) { 40 | this.mId = firstName.charAt(0) + "." + lastName.substring(0, 7) 41 | + "@" 42 | + division.substring(0, 5) + ".compa.ny"; 43 | } 44 | } 45 | // end::buildAndSendMail[] 46 | 47 | private MailMessage formatMessage(MailFont font, String string) { 48 | return null; 49 | } 50 | 51 | private class MailMan { 52 | public void send(String mId, String subject, MailMessage mMessage) {} 53 | public void sendMail(Mail mail) {} 54 | } 55 | 56 | private class MailFont {} 57 | 58 | private class MailMessage {} 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/chartlib/v1/Charts.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.chartlib.v1; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.Point; 5 | 6 | import eu.sig.training.ch05.boardpanel.v2.Rectangle; 7 | 8 | public class Charts { 9 | @SuppressWarnings("unused") 10 | // tag::drawBarChart[] 11 | public static void drawBarChart(Graphics g, 12 | CategoryItemRendererState state, 13 | Rectangle graphArea, 14 | CategoryPlot plot, 15 | CategoryAxis domainAxis, 16 | ValueAxis rangeAxis, 17 | CategoryDataset dataset) { 18 | // .. 19 | } 20 | // end::drawBarChart[] 21 | 22 | // tag::drawBarChartDefault[] 23 | public static void drawBarChart(Graphics g, CategoryDataset dataset) { 24 | Charts.drawBarChart(g, 25 | CategoryItemRendererState.DEFAULT, 26 | new Rectangle(new Point(0, 0), 100, 100), 27 | CategoryPlot.DEFAULT, 28 | CategoryAxis.DEFAULT, 29 | ValueAxis.DEFAULT, 30 | dataset); 31 | } 32 | // end::drawBarChartDefault[] 33 | } 34 | 35 | class CategoryItemRendererState { 36 | public static final CategoryItemRendererState DEFAULT = null; 37 | } 38 | 39 | class CategoryPlot { 40 | public static final CategoryPlot DEFAULT = null; 41 | } 42 | 43 | class CategoryAxis { 44 | public static final CategoryAxis DEFAULT = null; 45 | } 46 | 47 | class ValueAxis { 48 | public static final ValueAxis DEFAULT = null; 49 | } 50 | 51 | class CategoryDataset { 52 | public static final CategoryDataset DEFAULT = null; 53 | } 54 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch05/chartlib/v2/BarChart.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch05.chartlib.v2; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.Point; 5 | 6 | import eu.sig.training.ch05.boardpanel.v2.Rectangle; 7 | 8 | @SuppressWarnings("unused") 9 | // tag::BarChart[] 10 | public class BarChart { 11 | private CategoryItemRendererState state = CategoryItemRendererState.DEFAULT; 12 | private Rectangle graphArea = new Rectangle(new Point(0, 0), 100, 100); 13 | private CategoryPlot plot = CategoryPlot.DEFAULT; 14 | private CategoryAxis domainAxis = CategoryAxis.DEFAULT; 15 | private ValueAxis rangeAxis = ValueAxis.DEFAULT; 16 | private CategoryDataset dataset = CategoryDataset.DEFAULT; 17 | 18 | public BarChart draw(Graphics g) { 19 | // .. 20 | return this; 21 | } 22 | 23 | public ValueAxis getRangeAxis() { 24 | return rangeAxis; 25 | } 26 | 27 | public BarChart setRangeAxis(ValueAxis rangeAxis) { 28 | this.rangeAxis = rangeAxis; 29 | return this; 30 | } 31 | 32 | // More getters and setters. 33 | 34 | // end::BarChart[] 35 | 36 | public CategoryItemRendererState getState() { 37 | return state; 38 | } 39 | 40 | public BarChart setState(CategoryItemRendererState state) { 41 | this.state = state; 42 | return this; 43 | } 44 | 45 | public Rectangle getGraphArea() { 46 | return graphArea; 47 | } 48 | 49 | public BarChart setGraphArea(Rectangle graphArea) { 50 | this.graphArea = graphArea; 51 | return this; 52 | } 53 | 54 | public CategoryPlot getPlot() { 55 | return plot; 56 | } 57 | 58 | public BarChart setPlot(CategoryPlot plot) { 59 | this.plot = plot; 60 | return this; 61 | } 62 | 63 | public CategoryAxis getDomainAxis() { 64 | return domainAxis; 65 | } 66 | 67 | public BarChart setDomainAxis(CategoryAxis domainAxis) { 68 | this.domainAxis = domainAxis; 69 | return this; 70 | } 71 | 72 | public CategoryDataset getDataset() { 73 | return dataset; 74 | } 75 | 76 | public BarChart setDataset(CategoryDataset dataset) { 77 | this.dataset = dataset; 78 | return this; 79 | } 80 | 81 | } 82 | 83 | class CategoryItemRendererState { 84 | public static final CategoryItemRendererState DEFAULT = null; 85 | } 86 | 87 | class CategoryPlot { 88 | public static final CategoryPlot DEFAULT = null; 89 | } 90 | 91 | class CategoryAxis { 92 | public static final CategoryAxis DEFAULT = null; 93 | } 94 | 95 | class ValueAxis { 96 | public static final ValueAxis DEFAULT = null; 97 | } 98 | 99 | class CategoryDataset { 100 | public static final CategoryDataset DEFAULT = null; 101 | } 102 | 103 | @SuppressWarnings("serial") 104 | class BarChartTest extends java.awt.Frame { 105 | ValueAxis myValueAxis = null; 106 | CategoryDataset myDataset = null; 107 | @SuppressWarnings("unused") 108 | // tag::showMyBarChart[] 109 | private void showMyBarChart() { 110 | Graphics g = this.getGraphics(); 111 | BarChart b = new BarChart() 112 | .setRangeAxis(myValueAxis) 113 | .setDataset(myDataset) 114 | .draw(g); 115 | } 116 | // end::showMyBarChart[] 117 | } 118 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/advanceddigitalcamera/DigitalCamera.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.advanceddigitalcamera; 2 | 3 | import java.awt.Image; 4 | import java.awt.image.BufferedImage; 5 | 6 | @SuppressWarnings("unused") 7 | // tag::DigitalCamera[] 8 | public class DigitalCamera { 9 | public Image takeSnapshot() { 10 | // ... 11 | // end::DigitalCamera[] 12 | return new BufferedImage(1920, 1080, BufferedImage.TYPE_INT_ARGB); 13 | // tag::DigitalCamera[] 14 | } 15 | 16 | public void flashLightOn() { 17 | // ... 18 | } 19 | 20 | public void flaslLightOff() { 21 | // ... 22 | } 23 | 24 | public Image takePanoramaSnapshot() { 25 | // end::DigitalCamera[] 26 | return new BufferedImage(1920, 1080, BufferedImage.TYPE_INT_ARGB); 27 | // tag::DigitalCamera[] 28 | // ... 29 | } 30 | 31 | public Video record() { 32 | // ... 33 | // end::DigitalCamera[] 34 | return new Video(); 35 | // tag::DigitalCamera[] 36 | } 37 | 38 | public void setTimer(int seconds) { 39 | // ... 40 | } 41 | 42 | public void zoomIn() { 43 | // ... 44 | } 45 | 46 | public void zoomOut() { 47 | // ... 48 | } 49 | } 50 | // end::DigitalCamera[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/advanceddigitalcamera/Video.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.advanceddigitalcamera; 2 | 3 | public class Video { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/digitalcamera/DigitalCamera.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.digitalcamera; 2 | 3 | import java.awt.Image; 4 | import java.awt.image.BufferedImage; 5 | 6 | // tag::DigitalCamera[] 7 | public class DigitalCamera { 8 | public Image takeSnapshot() { 9 | // ... 10 | // end::DigitalCamera[] 11 | return new BufferedImage(1920, 1080, BufferedImage.TYPE_INT_ARGB); 12 | // tag::DigitalCamera[] 13 | } 14 | 15 | public void flashLightOn() { 16 | // ... 17 | } 18 | 19 | public void flaslLightOff() { 20 | // ... 21 | } 22 | } 23 | // end::DigitalCamera[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/digitalcamera/SmartphoneApp.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.digitalcamera; 2 | 3 | import java.awt.Image; 4 | 5 | @SuppressWarnings("unused") 6 | // tag::SmartphoneApp[] 7 | public class SmartphoneApp { 8 | private static DigitalCamera camera = new DigitalCamera(); 9 | 10 | public static void main(String[] args) { 11 | // ... 12 | Image image = camera.takeSnapshot(); 13 | // ... 14 | } 15 | } 16 | // end::SmartphoneApp[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/simpledigitalcamera/DigitalCamera.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.simpledigitalcamera; 2 | 3 | import java.awt.Image; 4 | 5 | // tag::DigitalCamera[] 6 | public class DigitalCamera implements SimpleDigitalCamera { 7 | // ... 8 | // end::DigitalCamera[] 9 | public Image takeSnapshot() { 10 | return null; 11 | } 12 | 13 | public void flashLightOn() {} 14 | 15 | public void flashLightOff() {} 16 | // tag::DigitalCamera[] 17 | } 18 | // end::DigitalCamera[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/simpledigitalcamera/SDK.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.simpledigitalcamera; 2 | 3 | public class SDK { 4 | 5 | public static SimpleDigitalCamera getCamera() { 6 | return new DigitalCamera(); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/simpledigitalcamera/SimpleDigitalCamera.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.simpledigitalcamera; 2 | 3 | import java.awt.Image; 4 | 5 | // tag::SimpleDigitalCamera[] 6 | public interface SimpleDigitalCamera { 7 | Image takeSnapshot(); 8 | 9 | void flashLightOn(); 10 | 11 | void flashLightOff(); 12 | } 13 | // end::SimpleDigitalCamera[] 14 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/simpledigitalcamera/SmartphoneApp.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.simpledigitalcamera; 2 | 3 | import java.awt.Image; 4 | 5 | @SuppressWarnings("unused") 6 | // tag::SmartphoneApp[] 7 | public class SmartphoneApp { 8 | private static SimpleDigitalCamera camera = SDK.getCamera(); 9 | 10 | public static void main(String[] args) { 11 | // ... 12 | Image image = camera.takeSnapshot(); 13 | // ... 14 | } 15 | } 16 | // end::SmartphoneApp[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/NotificationType.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice; 2 | 3 | public class NotificationType { 4 | 5 | public static NotificationType fromString(@SuppressWarnings("unused") String type) { 6 | return new NotificationType(); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/User.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice; 2 | 3 | public class User { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/UserInfo.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice; 2 | 3 | public class UserInfo { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/splitted/UserBlockService.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.splitted; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import eu.sig.training.ch06.userservice.User; 7 | 8 | @SuppressWarnings("unused") 9 | // tag::UserBlockService[] 10 | public class UserBlockService { 11 | public void blockUser(User user) { 12 | // ... 13 | } 14 | 15 | public List getAllBlockedUsers() { 16 | // ... 17 | // end::UserBlockService[] 18 | return new ArrayList(); 19 | // tag::UserBlockService[] 20 | } 21 | } 22 | // end::UserBlockService[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/splitted/UserNotificationService.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.splitted; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import eu.sig.training.ch06.userservice.NotificationType; 7 | import eu.sig.training.ch06.userservice.User; 8 | 9 | @SuppressWarnings("unused") 10 | // tag::UserNotificationService[] 11 | public class UserNotificationService { 12 | public List getNotificationTypes(User user) { 13 | // ... 14 | // end::UserNotificationService[] 15 | return new ArrayList(); 16 | // tag::UserNotificationService[] 17 | } 18 | 19 | public void register(User user, NotificationType type) { 20 | // ... 21 | } 22 | 23 | public void unregister(User user, NotificationType type) { 24 | // ... 25 | } 26 | } 27 | // end::UserNotificationService[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/splitted/UserService.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.splitted; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import eu.sig.training.ch06.userservice.User; 7 | import eu.sig.training.ch06.userservice.UserInfo; 8 | 9 | @SuppressWarnings("unused") 10 | // tag::UserService[] 11 | public class UserService { 12 | public User loadUser(String userId) { 13 | // ... 14 | // end::UserService[] 15 | return new User(); 16 | // tag::UserService[] 17 | } 18 | 19 | public boolean doesUserExist(String userId) { 20 | // ... 21 | // end::UserService[] 22 | return true; 23 | // tag::UserService[] 24 | } 25 | 26 | public User changeUserInfo(UserInfo userInfo) { 27 | // ... 28 | // end::UserService[] 29 | return new User(); 30 | // tag::UserService[] 31 | } 32 | 33 | public List searchUsers(UserInfo userInfo) { 34 | // ... 35 | // end::UserService[] 36 | return new ArrayList(); 37 | // tag::UserService[] 38 | } 39 | } 40 | // end::UserService[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/v1/UserRestAPI.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.v1; 2 | 3 | import javax.ws.rs.GET; 4 | import javax.ws.rs.Path; 5 | import javax.ws.rs.PathParam; 6 | import javax.ws.rs.core.Response; 7 | 8 | import eu.sig.training.ch06.userservice.User; 9 | 10 | // tag::UserRestAPI[] 11 | // The @Path and @GET attributes are defined by the the Java REST Service API 12 | @Path("/user") 13 | public class UserRestAPI { 14 | 15 | private final UserService userService = new UserService(); 16 | 17 | // ... 18 | // end::UserRestAPI[] 19 | public Response toJson(@SuppressWarnings("unused") User u) { 20 | return Response.accepted().build(); 21 | } 22 | // tag::UserRestAPI[] 23 | 24 | @GET 25 | @Path("/{userId}") 26 | public Response getUser(@PathParam(value = "userId") String userId) { 27 | User user = userService.loadUser(userId); 28 | return toJson(user); 29 | } 30 | } 31 | // end::UserRestAPI[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/v1/UserService.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.v1; 2 | 3 | import eu.sig.training.ch06.userservice.User; 4 | import eu.sig.training.ch06.userservice.UserInfo; 5 | 6 | @SuppressWarnings("unused") 7 | // tag::UserService[] 8 | public class UserService { 9 | public User loadUser(String userId) { 10 | // ... 11 | // end::UserService[] 12 | return new User(); 13 | // tag::UserService[] 14 | } 15 | 16 | public boolean doesUserExist(String userId) { 17 | // ... 18 | // end::UserService[] 19 | return true; 20 | // tag::UserService[] 21 | } 22 | 23 | public User changeUserInfo(UserInfo userInfo) { 24 | // ... 25 | // end::UserService[] 26 | return new User(); 27 | // tag::UserService[] 28 | } 29 | } 30 | // end::UserSerice[] 31 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/v2/NotificationRestAPI.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.v2; 2 | 3 | import javax.ws.rs.POST; 4 | import javax.ws.rs.Path; 5 | import javax.ws.rs.PathParam; 6 | import javax.ws.rs.core.Response; 7 | 8 | import org.apache.http.HttpStatus; 9 | 10 | import eu.sig.training.ch06.userservice.NotificationType; 11 | import eu.sig.training.ch06.userservice.User; 12 | 13 | // tag::NotificationRestAPI[] 14 | @Path("/notification") 15 | public class NotificationRestAPI { 16 | private final UserService userService = new UserService(); 17 | 18 | // ... 19 | // end::NotificationRestAPI[] 20 | public Response toJson(@SuppressWarnings("unused") int status) { 21 | return Response.accepted().build(); 22 | } 23 | // tag::NotificationRestAPI[] 24 | 25 | @POST 26 | @Path("/register/{userId}/{type}") 27 | public Response register(@PathParam(value = "userId") String userId, 28 | @PathParam(value = "type") String notificationType) { 29 | User user = userService.loadUser(userId); 30 | userService.registerForNotifications(user, NotificationType.fromString(notificationType)); 31 | return toJson(HttpStatus.SC_OK); 32 | } 33 | 34 | @POST 35 | @Path("/unregister/{userId}/{type}") 36 | public Response unregister(@PathParam(value = "userId") String userId, 37 | @PathParam(value = "type") String notificationType) { 38 | User user = userService.loadUser(userId); 39 | userService.unregisterForNotifications(user, NotificationType.fromString(notificationType)); 40 | return toJson(HttpStatus.SC_OK); 41 | } 42 | } 43 | // end::NotificationRestAPI[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/v2/UserService.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.v2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import eu.sig.training.ch06.userservice.NotificationType; 7 | import eu.sig.training.ch06.userservice.User; 8 | import eu.sig.training.ch06.userservice.UserInfo; 9 | 10 | @SuppressWarnings("unused") 11 | // tag::UserService[] 12 | public class UserService { 13 | public User loadUser(String userId) { 14 | // ... 15 | // end::UserService[] 16 | return new User(); 17 | // tag::UserService[] 18 | } 19 | 20 | public boolean doesUserExist(String userId) { 21 | // ... 22 | // end::UserService[] 23 | return true; 24 | // tag::UserService[] 25 | } 26 | 27 | public User changeUserInfo(UserInfo userInfo) { 28 | // ... 29 | // end::UserService[] 30 | return new User(); 31 | // tag::UserService[] 32 | } 33 | 34 | public List getNotificationTypes(User user) { 35 | // ... 36 | // end::UserService[] 37 | return new ArrayList(); 38 | // tag::UserService[] 39 | } 40 | 41 | public void registerForNotifications(User user, NotificationType type) { 42 | // ... 43 | } 44 | 45 | public void unregisterForNotifications(User user, NotificationType type) { 46 | // ... 47 | } 48 | } 49 | // end::UserSerice[] 50 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch06/userservice/v3/UserService.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch06.userservice.v3; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import eu.sig.training.ch06.userservice.NotificationType; 7 | import eu.sig.training.ch06.userservice.User; 8 | import eu.sig.training.ch06.userservice.UserInfo; 9 | 10 | @SuppressWarnings("unused") 11 | // tag::UserService[] 12 | public class UserService { 13 | public User loadUser(String userId) { 14 | // ... 15 | // end::UserService[] 16 | return new User(); 17 | // tag::UserService[] 18 | } 19 | 20 | public boolean doesUserExist(String userId) { 21 | // ... 22 | // end::UserService[] 23 | return true; 24 | // tag::UserService[] 25 | } 26 | 27 | public User changeUserInfo(UserInfo userInfo) { 28 | // ... 29 | // end::UserService[] 30 | return new User(); 31 | // tag::UserService[] 32 | } 33 | 34 | public List getNotificationTypes(User user) { 35 | // ... 36 | // end::UserService[] 37 | return new ArrayList(); 38 | // tag::UserService[] 39 | } 40 | 41 | public void registerForNotifications(User user, NotificationType type) { 42 | // ... 43 | } 44 | 45 | public void unregisterForNotifications(User user, NotificationType type) { 46 | // ... 47 | } 48 | 49 | public List searchUsers(UserInfo userInfo) { 50 | // ... 51 | // end::UserService[] 52 | return new ArrayList(); 53 | // tag::UserService[] 54 | } 55 | 56 | public void blockUser(User user) { 57 | // ... 58 | } 59 | 60 | public List getAllBlockedUsers() { 61 | // ... 62 | // end::UserService[] 63 | return new ArrayList(); 64 | // tag::UserService[] 65 | } 66 | } 67 | // end::UserSerice[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AWSCloudServerFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | // tag::AWSCloudServerFactory[] 4 | public class AWSCloudServerFactory implements CloudServerFactory { 5 | public CloudServer launchComputeServer() { 6 | return new AWSComputeServer(); 7 | } 8 | 9 | public CloudServer launchDatabaseServer() { 10 | return new AWSDatabaseServer(); 11 | } 12 | 13 | public CloudStorage createCloudStorage(long sizeGb) { 14 | return new AWSCloudStorage(sizeGb); 15 | } 16 | } 17 | // end::AWSCloudServerFactory[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AWSCloudStorage.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public class AWSCloudStorage implements CloudStorage { 4 | 5 | public AWSCloudStorage(@SuppressWarnings("unused") long sizeGb) {} 6 | 7 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AWSComputeServer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public class AWSComputeServer implements CloudServer { 4 | 5 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AWSDatabaseServer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public class AWSDatabaseServer implements CloudServer { 4 | 5 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/ApplicationLauncher.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | @SuppressWarnings("unused") 4 | // tag::ApplicationLauncher[] 5 | public class ApplicationLauncher { 6 | 7 | public static void main(String[] args) { 8 | CloudServerFactory factory; 9 | if (args[1].equals("-azure")) { 10 | factory = new AzureCloudServerFactory(); 11 | } else { 12 | factory = new AWSCloudServerFactory(); 13 | } 14 | CloudServer computeServer = factory.launchComputeServer(); 15 | CloudServer databaseServer = factory.launchDatabaseServer(); 16 | // end::ApplicationLauncher[] 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AzureCloudServerFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | // tag::AzureCloudServerFactory[] 4 | public class AzureCloudServerFactory implements CloudServerFactory { 5 | public CloudServer launchComputeServer() { 6 | return new AzureComputeServer(); 7 | } 8 | 9 | public CloudServer launchDatabaseServer() { 10 | return new AzureDatabaseServer(); 11 | } 12 | 13 | public CloudStorage createCloudStorage(long sizeGb) { 14 | return new AzureCloudStorage(sizeGb); 15 | } 16 | } 17 | // end::AzureCloudServerFactory[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AzureCloudStorage.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public class AzureCloudStorage implements CloudStorage { 4 | public AzureCloudStorage(@SuppressWarnings("unused") long sizeGb) {} 5 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AzureComputeServer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public class AzureComputeServer implements CloudServer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/AzureDatabaseServer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public class AzureDatabaseServer implements CloudServer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/CloudServer.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public interface CloudServer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/CloudServerFactory.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | // tag::CloudServerFactory[] 4 | public interface CloudServerFactory { 5 | CloudServer launchComputeServer(); 6 | 7 | CloudServer launchDatabaseServer(); 8 | 9 | CloudStorage createCloudStorage(long sizeGb); 10 | } 11 | // end::CloudServerFactory[] -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch07/CloudStorage.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch07; 2 | 3 | public interface CloudStorage { 4 | 5 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch10/PerfectPicture.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch10; 2 | 3 | import java.awt.Image; 4 | 5 | import eu.sig.training.ch06.simpledigitalcamera.SimpleDigitalCamera; 6 | 7 | public class PerfectPicture { 8 | public static SimpleDigitalCamera camera = null; 9 | 10 | // tag::takePerfectPicture[] 11 | public final static int DAYLIGHT_START = 6; 12 | 13 | public Image takePerfectPicture(int currentHour) { 14 | Image image; 15 | if (currentHour < PerfectPicture.DAYLIGHT_START) { 16 | camera.flashLightOn(); 17 | image = camera.takeSnapshot(); 18 | camera.flashLightOff(); 19 | } else { 20 | image = camera.takeSnapshot(); 21 | } 22 | return image; 23 | } 24 | // end::takePerfectPicture[] 25 | } 26 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch10/Program.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch10; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | import eu.sig.training.ch04.v1.Accounts; 8 | 9 | public class Program { 10 | public static void main(String[] args) throws IOException { 11 | BufferedReader isr = 12 | new BufferedReader(new InputStreamReader(System.in)); 13 | String acct; 14 | do { 15 | System.out.println("Type a bank account number on the next line."); 16 | acct = isr.readLine(); 17 | System.out.println("Bank account number '" + acct + "' is" + 18 | (Accounts.isValid(acct) ? "" : " not") + " valid."); 19 | } while (acct != null && acct.length() != 0); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch11/DeadCode.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch11; 2 | 3 | public class DeadCode { 4 | public class Transaction { 5 | public Transaction(@SuppressWarnings("unused") long uid) { 6 | } 7 | } 8 | 9 | @SuppressWarnings("unused") 10 | // tag::getTransaction[] 11 | public Transaction getTransaction(long uid) { 12 | Transaction result = new Transaction(uid); 13 | if (result != null) { 14 | return result; 15 | } else { 16 | return lookupTransaction(uid); // <1> 17 | } 18 | } 19 | // end::getTransaction[] 20 | 21 | private Transaction lookupTransaction( 22 | @SuppressWarnings("unused") long uid) { 23 | return null; 24 | } 25 | } -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch11/MagicConstants.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch11; 2 | 3 | public class MagicConstants { 4 | 5 | public class Customer { 6 | private final int age; 7 | 8 | public Customer(int age) { 9 | this.age = age; 10 | } 11 | 12 | public int getAge() { 13 | return age; 14 | } 15 | } 16 | 17 | public class UseMagicConstants { 18 | 19 | // tag::calculateFareMagicConstants[] 20 | float calculateFare(Customer c, long distance) { 21 | float travelledDistanceFare = distance * 0.10f; 22 | if (c.getAge() < 12) { 23 | travelledDistanceFare *= 0.25f; 24 | } else 25 | if (c.getAge() >= 65) { 26 | travelledDistanceFare *= 0.5f; 27 | } 28 | return 3.00f + travelledDistanceFare; 29 | } 30 | // end::calculateFareMagicConstants[] 31 | 32 | } 33 | 34 | public class DoNotUseMagicConstants { 35 | // tag::calculateFareDoNotUseMagicConstants[] 36 | private static final float BASE_RATE = 3.00f; 37 | private static final float FARE_PER_KM = 0.10f; 38 | private static final float DISCOUNT_RATE_CHILDREN = 0.25f; 39 | private static final float DISCOUNT_RATE_ELDERLY = 0.5f; 40 | private static final int MAXIMUM_AGE_CHILDREN = 12; 41 | private static final int MINIMUM_AGE_ELDERLY = 65; 42 | 43 | float calculateFare(Customer c, long distance) { 44 | float travelledDistanceFare = distance * FARE_PER_KM; 45 | if (c.getAge() < MAXIMUM_AGE_CHILDREN) { 46 | travelledDistanceFare *= DISCOUNT_RATE_CHILDREN; 47 | } else 48 | if (c.getAge() >= MINIMUM_AGE_ELDERLY) { 49 | travelledDistanceFare *= DISCOUNT_RATE_ELDERLY; 50 | } 51 | return BASE_RATE + travelledDistanceFare; 52 | } 53 | // end::calculateFareDoNotUseMagicConstants[] 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch11/StandardContext.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch11; 2 | 3 | public class StandardContext { 4 | 5 | @SuppressWarnings("unused") 6 | // tag::validateFilterMap[] 7 | private void validateFilterMap(FilterMap filterMap) { 8 | // Validate the proposed filter mapping 9 | String filterName = filterMap.getFilterName(); 10 | String[] servletNames = filterMap.getServletNames(); 11 | String[] urlPatterns = filterMap.getURLPatterns(); 12 | if (findFilterDef(filterName) == null) 13 | throw new IllegalArgumentException( 14 | sm.getString("standardContext.filterMap.name", filterName)); 15 | 16 | if (!filterMap.getMatchAllServletNames() && 17 | !filterMap.getMatchAllUrlPatterns() && 18 | (servletNames.length == 0) && (urlPatterns.length == 0)) 19 | throw new IllegalArgumentException( 20 | sm.getString("standardContext.filterMap.either")); 21 | // FIXME: Older spec revisions may still check this 22 | /* 23 | if ((servletNames.length != 0) && (urlPatterns.length != 0)) 24 | throw new IllegalArgumentException 25 | (sm.getString("standardContext.filterMap.either")); 26 | */ 27 | for (int i = 0; i < urlPatterns.length; i++) { 28 | if (!validateURLPattern(urlPatterns[i])) { 29 | throw new IllegalArgumentException( 30 | sm.getString("standardContext.filterMap.pattern", 31 | urlPatterns[i])); 32 | } 33 | } 34 | } 35 | // end::validateFilterMap[] 36 | 37 | public class GetStringObject { 38 | public String getString(String string) { 39 | return string; 40 | } 41 | 42 | public String getString(String string, 43 | @SuppressWarnings("unused") Object o) { 44 | return string; 45 | } 46 | } 47 | 48 | private GetStringObject sm = new GetStringObject(); 49 | 50 | public class FilterMap { 51 | 52 | public boolean getMatchAllUrlPatterns() { 53 | return false; 54 | } 55 | 56 | public String[] getURLPatterns() { 57 | return null; 58 | } 59 | 60 | public String[] getServletNames() { 61 | return null; 62 | } 63 | 64 | public String getFilterName() { 65 | return null; 66 | } 67 | 68 | public boolean getMatchAllServletNames() { 69 | return false; 70 | } 71 | 72 | } 73 | 74 | private boolean validateURLPattern( 75 | @SuppressWarnings("unused") String string) { 76 | return false; 77 | } 78 | 79 | private Object findFilterDef( 80 | @SuppressWarnings("unused") String filterName) { 81 | return null; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/java/eu/sig/training/ch11/ValuableVsNonValuableComments.java: -------------------------------------------------------------------------------- 1 | // This unit suggest labels for autocompletion 2 | public AutoCompletionCandidates doAutoCompleteLabels(@QueryParameter String value) { 3 | AutoCompletionCandidates result = new AutoCompletionCandidates(); 4 | // show all suggestions for short strings 5 | if (query.length() < 2) { 6 | result.add(getProjectLabelsAsArray(job)); 7 | } else { 8 | for (String branch : getProjectLabelsAsArray(job)) { 9 | if (branch.toLowerCase().contains(query.toLowerCase())) { 10 | result.add(branch); 11 | } 12 | } 13 | } 14 | return result; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/csharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("maintainabilitybooktests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Vagrant Inc.")] 11 | [assembly: AssemblyProduct("maintainabilitybooktests.Properties")] 12 | [assembly: AssemblyCopyright("Software Improvement Group")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("f00adb74-f9a6-4f53-8f36-2963d85c4319")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | [assembly: AssemblyVersion("1.0.*")] 32 | [assembly: AssemblyFileVersion("1.0.0.0")] 33 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch03/FlagFactoryWithMapTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | 5 | namespace eu.sig.training.ch03 6 | { 7 | [TestFixture] 8 | public class FlagFactoryWithMapTest 9 | { 10 | 11 | [Test] 12 | public void TestGetFlagColors() 13 | { 14 | FlagFactoryWithMap factory = new FlagFactoryWithMap(); 15 | 16 | IList colors = factory.GetFlagColors(Nationality.DUTCH); 17 | 18 | Assert.AreEqual(Color.Red, colors[0]); 19 | Assert.AreEqual(Color.White, colors[1]); 20 | Assert.AreEqual(Color.Blue, colors[2]); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch03/FlagsTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | 5 | namespace eu.sig.training.ch03 6 | { 7 | [TestFixture] 8 | public class FlagsTest 9 | { 10 | 11 | [Test] 12 | public void testGetFlag() 13 | { 14 | FlagFactory factory = new FlagFactory(); 15 | 16 | IList colors = factory.GetFlagColors(Nationality.DUTCH); 17 | 18 | Assert.AreEqual(Color.Red, colors[0]); 19 | Assert.AreEqual(Color.White, colors[1]); 20 | Assert.AreEqual(Color.Blue, colors[2]); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch03/binarytree/BinaryTreeSearchTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace eu.sig.training.ch03.binarytree 5 | { 6 | [TestFixture] 7 | public class BinaryTreeSearchTest 8 | { 9 | 10 | [Test] 11 | public void testSimpleTree() 12 | { 13 | BinaryTreeNode root = new BinaryTreeNode(5); 14 | root.Insert(3); 15 | root.Insert(10); 16 | root.Insert(12); 17 | 18 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v1.BinaryTreeSearch.CalculateDepth(root, 12), 2); 19 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v2.BinaryTreeSearch.CalculateDepth(root, 12), 2); 20 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v3.BinaryTreeSearch.CalculateDepth(root, 12), 2); 21 | } 22 | 23 | [Test] 24 | public void testDepth0() 25 | { 26 | BinaryTreeNode root = new BinaryTreeNode(2); 27 | root.Insert(5); 28 | root.Insert(1); 29 | root.Insert(16); 30 | 31 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v1.BinaryTreeSearch.CalculateDepth(root, 2), 0); 32 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v2.BinaryTreeSearch.CalculateDepth(root, 2), 0); 33 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v3.BinaryTreeSearch.CalculateDepth(root, 2), 0); 34 | } 35 | 36 | [Test] 37 | public void testNotInTree() 38 | { 39 | BinaryTreeNode root = new BinaryTreeNode(2); 40 | root.Insert(5); 41 | root.Insert(1); 42 | root.Insert(16); 43 | bool exceptionCaught_v1 = false; 44 | bool exceptionCaught_v2 = false; 45 | bool exceptionCaught_v3 = false; 46 | 47 | #pragma warning disable 168 48 | try 49 | { 50 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v1.BinaryTreeSearch.CalculateDepth(root, 17), 0); 51 | } 52 | catch (TreeException e) 53 | { 54 | exceptionCaught_v1 = true; 55 | } 56 | try 57 | { 58 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v2.BinaryTreeSearch 59 | .CalculateDepth(root, 17), 0); 60 | } 61 | catch (TreeException e) 62 | { 63 | exceptionCaught_v2 = true; 64 | } 65 | try 66 | { 67 | Assert.AreEqual(eu.sig.training.ch03.binarytree.v3.BinaryTreeSearch 68 | .CalculateDepth(root, 17), 0); 69 | } 70 | catch (TreeException e) 71 | { 72 | exceptionCaught_v3 = true; 73 | } 74 | Assert.IsTrue(exceptionCaught_v1); 75 | Assert.IsTrue(exceptionCaught_v2); 76 | Assert.IsTrue(exceptionCaught_v3); 77 | #pragma warning restore 168 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch03/withmapandtypes/FlagsTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | 5 | namespace eu.sig.training.ch03.withmapandtypes 6 | { 7 | [TestFixture] 8 | public class FlagsTest 9 | { 10 | 11 | [Test] 12 | public void TestGetFlag() 13 | { 14 | FlagFactory factory = new FlagFactory(); 15 | 16 | IList colors = factory.GetFlagColors(Nationality.DUTCH); 17 | 18 | Assert.AreEqual(Color.Red, colors[0]); 19 | Assert.AreEqual(Color.White, colors[1]); 20 | Assert.AreEqual(Color.Blue, colors[2]); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch04/v1/AccountsTest.cs: -------------------------------------------------------------------------------- 1 | // tag::AccountsTest[] 2 | using NUnit.Framework; 3 | 4 | namespace eu.sig.training.ch04.v1 5 | { 6 | [TestFixture] 7 | public class AccountsTest 8 | { 9 | [Test] 10 | public void TestIsValidNormalCases() 11 | { 12 | Assert.IsTrue(Accounts.IsValid("123456789")); 13 | Assert.IsFalse(Accounts.IsValid("123456788")); 14 | } 15 | 16 | // end::AccountsTest[] 17 | 18 | // This test is meant to fail. 19 | [Ignore("Deliberately fails for illustration purpose")] 20 | // tag::testEmptyString[] 21 | [Test] 22 | public void TestEmptyString() 23 | { 24 | Assert.IsFalse(Accounts.IsValid("")); 25 | } 26 | // end::testEmptyString[] 27 | 28 | #pragma warning disable 219 29 | // This test is meant to fail, that's why we ignore it. 30 | [Ignore("Deliberately fails for illustration purpose")] 31 | // tag::showError[] 32 | [Test] 33 | public void ShowError() 34 | { 35 | int tmp = 0, dummy = 1 / tmp; 36 | // Next line is never executed because the previous one raises an 37 | // exception. 38 | // If it were executed, you'll never see the assert message because 39 | // the test always succeeds. 40 | Assert.IsTrue(true); 41 | } 42 | // end::showError[] 43 | #pragma warning restore 219 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch04/v3/CheckingAccountTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace eu.sig.training.ch04.v3 4 | { 5 | 6 | [TestFixture] 7 | public class CheckingsAccountTest 8 | { 9 | 10 | CheckingAccount myAccount; 11 | CheckingAccount counterAccount; 12 | 13 | [SetUp] 14 | public void Init() 15 | { 16 | myAccount = Accounts.MakeAccount("123456789"); 17 | counterAccount = Accounts.MakeAccount("497164833"); 18 | } 19 | 20 | [Test] 21 | [ExpectedException(typeof(BusinessException))] 22 | public void TestTransferLimit() 23 | { 24 | myAccount.MakeTransfer(Accounts.GetAccountNumber(counterAccount), new Money()); 25 | } 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch04/v3/SavingsAccountTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace eu.sig.training.ch04.v3 4 | { 5 | 6 | [TestFixture] 7 | public class SavingsAccountTest 8 | { 9 | 10 | SavingsAccount myAccount; 11 | CheckingAccount registeredCounterAccount; 12 | 13 | [SetUp] 14 | public void Init() 15 | { 16 | myAccount = Accounts.MakeAccount("123456789"); 17 | registeredCounterAccount = Accounts.MakeAccount("497164833"); 18 | myAccount.RegisteredCounterAccount = registeredCounterAccount; 19 | } 20 | 21 | [Test] 22 | public void TestCounterAccount() 23 | { 24 | myAccount.MakeTransfer("497164833", new Money()); 25 | } 26 | 27 | [Test] 28 | [ExpectedException(typeof(BusinessException))] 29 | public void TestNoCounterAccount() 30 | { 31 | CheckingAccount unRegisteredCounterAccount = Accounts.MakeAccount("1439"); 32 | myAccount.MakeTransfer(Accounts.GetAccountNumber(unRegisteredCounterAccount), new Money()); 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch04/v4/AccountsTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace eu.sig.training.ch04.v4 4 | { 5 | [TestFixture] 6 | public class AccountsTest 7 | { 8 | 9 | [Test] 10 | public void TestIsValidNormalCases() 11 | { 12 | Assert.IsTrue(Accounts.IsValid("123456789")); 13 | Assert.IsFalse(Accounts.IsValid("123456788")); 14 | } 15 | 16 | [Test] 17 | public void TestIsValidLetters() 18 | { 19 | Assert.IsFalse(Accounts.IsValid("ABCDEFGHK")); 20 | } 21 | 22 | [Test] 23 | public void TestIsValidNonNormal() 24 | { 25 | Assert.IsFalse(Accounts.IsValid("")); 26 | } 27 | 28 | [Test] 29 | public void TestIsValidNonNumeric() 30 | { 31 | Assert.IsFalse(Accounts.IsValid("12.34.56.")); 32 | } 33 | 34 | [Test] 35 | public void TestIsValidToolong() 36 | { 37 | Assert.IsFalse(Accounts.IsValid("1234567890")); 38 | } 39 | 40 | [Test] 41 | public void TestIsValidTooshort() 42 | { 43 | Assert.IsFalse(Accounts.IsValid("12345677")); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch06/userservice/v1/UserControllerTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Http; 3 | using System.Web.Http.Results; 4 | using NUnit.Framework; 5 | 6 | using eu.sig.training.ch06.userservice; 7 | 8 | namespace eu.sig.training.ch06.userservice.v1 9 | { 10 | [TestFixture] 11 | class UserControllerTest 12 | { 13 | [Test] 14 | public void TestGetUserById() 15 | { 16 | UserController controller = new UserController(); 17 | IHttpActionResult action = controller.GetUserById("user@example.com"); 18 | var result = action as OkNegotiatedContentResult; 19 | Assert.AreEqual("user@example.com", result.Content.Id); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch06/userservice/v2/NotificationControllerTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Http; 3 | using System.Web.Http.Results; 4 | using NUnit.Framework; 5 | 6 | using eu.sig.training.ch06.userservice; 7 | 8 | namespace eu.sig.training.ch06.userservice.v2 9 | { 10 | [TestFixture] 11 | class NotificationControllerTest 12 | { 13 | private NotificationController controller; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | NotificationController controller = new NotificationController(); 19 | } 20 | 21 | [Test] 22 | public void TestRegister() 23 | { 24 | IHttpActionResult action = controller.Register("user@example.com", ""); 25 | var result = action as OkNegotiatedContentResult; 26 | Assert.AreEqual("user@example.com", result.Content.Name); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch10/PerfectPictureMockTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Drawing; 3 | using eu.sig.training.ch06.simpledigitalcamera; 4 | using Moq; 5 | 6 | namespace eu.sig.training.ch10 7 | { 8 | [TestFixture] 9 | public class PerfectPictureMoqTest 10 | { 11 | // tag::testNightPictureMockito[] 12 | [Test] 13 | public void TestNightPictureMoq() 14 | { 15 | Image image = 16 | Image.FromFile("../../../../test/resources/VanGoghStarryNight.jpg"); 17 | var cameraMock = new Mock(); 18 | cameraMock.Setup(foo => foo.TakeSnapshot()).Returns(image); 19 | PerfectPicture.camera = cameraMock.Object; 20 | Assert.AreSame(image, new PerfectPicture().TakePerfectPicture(0)); 21 | cameraMock.Verify(foo => foo.FlashLightOn(), Times.AtMostOnce()); 22 | } 23 | // end::testNightPictureMockito[] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/csharp/eu/sig/training/ch10/PerfectPictureTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Drawing; 3 | using eu.sig.training.ch06.simpledigitalcamera; 4 | 5 | namespace eu.sig.training.ch10 6 | { 7 | 8 | [TestFixture] 9 | public class PerfectPictureTest 10 | { 11 | 12 | // tag::testDayPicture[] 13 | [Test] 14 | public void TestDayPicture() 15 | { 16 | Image image = 17 | Image.FromFile("../../../../test/resources/VanGoghSunflowers.jpg"); 18 | DigitalCameraStub cameraStub = new DigitalCameraStub(); 19 | cameraStub.TestImage = image; 20 | PerfectPicture.camera = cameraStub; 21 | Assert.AreSame(image, new PerfectPicture().TakePerfectPicture(12)); 22 | } 23 | // end::testDayPicture[] 24 | 25 | // tag::testNightPicture[] 26 | [Test] 27 | public void TestNightPicture() 28 | { 29 | Image image = 30 | Image.FromFile("../../../../test/resources/VanGoghStarryNight.jpg"); 31 | DigitalCameraMock cameraMock = new DigitalCameraMock(); 32 | cameraMock.TestImage = image; 33 | PerfectPicture.camera = cameraMock; 34 | Assert.AreSame(image, new PerfectPicture().TakePerfectPicture(0)); 35 | Assert.AreEqual(1, cameraMock.FlashOnCounter); 36 | } 37 | // end::testNightPicture[] 38 | 39 | } 40 | 41 | // tag::DigitalCameraStub[] 42 | class DigitalCameraStub : ISimpleDigitalCamera 43 | { 44 | public Image TestImage; 45 | 46 | public Image TakeSnapshot() 47 | { 48 | return this.TestImage; 49 | } 50 | 51 | public void FlashLightOn() 52 | { 53 | } 54 | 55 | public void FlashLightOff() 56 | { 57 | } 58 | } 59 | // end::DigitalCameraStub[] 60 | 61 | // tag::DigitalCameraMock[] 62 | class DigitalCameraMock : ISimpleDigitalCamera 63 | { 64 | public Image TestImage; 65 | public int FlashOnCounter = 0; 66 | 67 | public Image TakeSnapshot() 68 | { 69 | return this.TestImage; 70 | } 71 | 72 | public void FlashLightOn() 73 | { 74 | this.FlashOnCounter++; 75 | } 76 | 77 | public void FlashLightOff() 78 | { 79 | } 80 | } 81 | // end::DigitalCameraMock[] 82 | } 83 | -------------------------------------------------------------------------------- /src/test/csharp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch03/FlagFactoryWithMapTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.awt.Color; 6 | import java.util.List; 7 | 8 | import org.junit.Test; 9 | 10 | public class FlagFactoryWithMapTest { 11 | 12 | @Test 13 | public void testGetFlagColors() { 14 | FlagFactoryWithMap factory = new FlagFactoryWithMap(); 15 | 16 | List colors = factory.getFlagColors(Nationality.DUTCH); 17 | 18 | assertEquals(Color.RED, colors.get(0)); 19 | assertEquals(Color.WHITE, colors.get(1)); 20 | assertEquals(Color.BLUE, colors.get(2)); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch03/FlagsTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.awt.Color; 6 | import java.util.List; 7 | 8 | import org.junit.Test; 9 | 10 | public class FlagsTest { 11 | 12 | @Test 13 | public void testGetFlag() { 14 | FlagFactory factory = new FlagFactory(); 15 | 16 | List colors = factory.getFlagColors(Nationality.DUTCH); 17 | 18 | assertEquals(Color.RED, colors.get(0)); 19 | assertEquals(Color.WHITE, colors.get(1)); 20 | assertEquals(Color.BLUE, colors.get(2)); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch03/binarytree/BinaryTreeSearchTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch03.binarytree; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | public class BinaryTreeSearchTest { 9 | 10 | @Test 11 | public void testSimpleTree() { 12 | BinaryTreeNode root = new BinaryTreeNode(5); 13 | root.insert(3); 14 | root.insert(10); 15 | root.insert(12); 16 | 17 | assertEquals(eu.sig.training.ch03.binarytree.v1.BinaryTreeSearch.calculateDepth(root, 12), 2); 18 | assertEquals(eu.sig.training.ch03.binarytree.v2.BinaryTreeSearch.calculateDepth(root, 12), 2); 19 | assertEquals(eu.sig.training.ch03.binarytree.v3.BinaryTreeSearch.calculateDepth(root, 12), 2); 20 | } 21 | 22 | @Test 23 | public void testDepth0() { 24 | BinaryTreeNode root = new BinaryTreeNode(2); 25 | root.insert(5); 26 | root.insert(1); 27 | root.insert(16); 28 | 29 | assertEquals(eu.sig.training.ch03.binarytree.v1.BinaryTreeSearch.calculateDepth(root, 2), 0); 30 | assertEquals(eu.sig.training.ch03.binarytree.v2.BinaryTreeSearch.calculateDepth(root, 2), 0); 31 | assertEquals(eu.sig.training.ch03.binarytree.v3.BinaryTreeSearch.calculateDepth(root, 2), 0); 32 | } 33 | 34 | @Test 35 | public void testNotInTree() { 36 | BinaryTreeNode root = new BinaryTreeNode(2); 37 | root.insert(5); 38 | root.insert(1); 39 | root.insert(16); 40 | boolean exceptionCaught_v1 = false; 41 | boolean exceptionCaught_v2 = false; 42 | boolean exceptionCaught_v3 = false; 43 | 44 | try { 45 | assertEquals(eu.sig.training.ch03.binarytree.v1.BinaryTreeSearch.calculateDepth(root, 17), 0); 46 | } catch (TreeException e) { 47 | exceptionCaught_v1 = true; 48 | } 49 | try { 50 | assertEquals(eu.sig.training.ch03.binarytree.v2.BinaryTreeSearch 51 | .calculateDepth(root, 17), 0); 52 | } catch (TreeException e) { 53 | exceptionCaught_v2 = true; 54 | } 55 | try { 56 | assertEquals(eu.sig.training.ch03.binarytree.v3.BinaryTreeSearch 57 | .calculateDepth(root, 17), 0); 58 | } catch (TreeException e) { 59 | exceptionCaught_v3 = true; 60 | } 61 | assertTrue(exceptionCaught_v1); 62 | assertTrue(exceptionCaught_v2); 63 | assertTrue(exceptionCaught_v3); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch04/v1/AccountsTest.java: -------------------------------------------------------------------------------- 1 | // tag::AccountsTest[] 2 | package eu.sig.training.ch04.v1; 3 | 4 | import static org.junit.Assert.assertFalse; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import org.junit.Ignore; 8 | import org.junit.Test; 9 | 10 | public class AccountsTest { 11 | 12 | @Test 13 | public void testIsValidNormalCases() { 14 | assertTrue(Accounts.isValid("123456789")); 15 | assertFalse(Accounts.isValid("123456788")); 16 | } 17 | 18 | // end::AccountsTest[] 19 | 20 | @Ignore("Deliberately fails for illustration purpose") 21 | // tag::testEmptyString[] 22 | @Test 23 | public void testEmptyString() { 24 | assertFalse(Accounts.isValid("")); 25 | } 26 | // end::testEmptyString[] 27 | 28 | @SuppressWarnings("unused") 29 | @Ignore("Deliberately fails for illustration purpose") 30 | // tag::showError[] 31 | @Test 32 | public void showError() { 33 | int dummy = 1 / 0; 34 | // Next line is never executed because the previous one raises an 35 | // exception. 36 | // If it were executed, you'll never see the assert message because 37 | // the test always succeeds. 38 | assertTrue("You will never see this text.", true); 39 | } 40 | // end::showError[] 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch04/v3/CheckingAccountTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v3; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import eu.sig.training.ch04.BusinessException; 7 | import eu.sig.training.ch04.Money; 8 | 9 | public class CheckingAccountTest { 10 | 11 | CheckingAccount myAccount; 12 | CheckingAccount counterAccount; 13 | 14 | @Before 15 | public void setUp() { 16 | myAccount = Accounts.makeAccount(CheckingAccount.class, "123456789"); 17 | counterAccount = 18 | Accounts.makeAccount(CheckingAccount.class, "497164833"); 19 | } 20 | 21 | @Test(expected = BusinessException.class) 22 | public void TestTransferLimit() throws BusinessException { 23 | myAccount.makeTransfer(Accounts.getAccountNumber(counterAccount), 24 | new Money()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch04/v3/SavingsAccountTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v3; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import eu.sig.training.ch04.BusinessException; 7 | import eu.sig.training.ch04.Money; 8 | 9 | public class SavingsAccountTest { 10 | 11 | SavingsAccount myAccount; 12 | CheckingAccount registeredCounterAccount; 13 | 14 | @Before 15 | public void setUp() { 16 | myAccount = Accounts.makeAccount(SavingsAccount.class, "123456789"); 17 | registeredCounterAccount = 18 | Accounts.makeAccount(CheckingAccount.class, "497164833"); 19 | myAccount.registeredCounterAccount = registeredCounterAccount; 20 | } 21 | 22 | @Test 23 | public void testCounterAccount() throws BusinessException { 24 | myAccount.makeTransfer("497164833", new Money()); 25 | } 26 | 27 | @Test(expected = BusinessException.class) 28 | public void testNoCounterAccount() throws BusinessException { 29 | CheckingAccount unRegisteredCounterAccount = 30 | Accounts.makeAccount(CheckingAccount.class, "1439"); 31 | myAccount.makeTransfer( 32 | Accounts.getAccountNumber(unRegisteredCounterAccount), new Money()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch04/v4/AccountsTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch04.v4; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | public class AccountsTest { 9 | 10 | @Test 11 | public void testIsValidNormalCases() { 12 | assertTrue("isValid(\"123456789\") should return true", 13 | Accounts.isValid("123456789")); 14 | assertFalse("isValid(\"123456788\") should return false", 15 | Accounts.isValid("123456788")); 16 | } 17 | 18 | @Test 19 | public void testIsValidLetters() { 20 | assertFalse("isValid(\"abcdefghi\") should return false", 21 | Accounts.isValid("ABCDEFGHK")); 22 | } 23 | 24 | @Test 25 | public void testIsValidNonNormal() { 26 | assertFalse("Empty string is not a valid number", Accounts.isValid("")); 27 | } 28 | 29 | @Test 30 | public void testIsValidNonNumeric() { 31 | assertFalse("Non-numerics always invalid", 32 | Accounts.isValid("12.34.56.")); 33 | } 34 | 35 | @Test 36 | public void testIsValidToolong() { 37 | assertFalse("More than 9 digits is always invalid", 38 | Accounts.isValid("1234567890")); 39 | } 40 | 41 | @Test 42 | public void testIsValidTooshort() { 43 | assertFalse("Less than 9 digits is always invalid", 44 | Accounts.isValid("12345677")); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch10/PerfectPictureMockTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch10; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.mockito.Mockito.mock; 5 | import static org.mockito.Mockito.verify; 6 | import static org.mockito.Mockito.when; 7 | 8 | import java.awt.image.BufferedImage; 9 | import java.io.File; 10 | import java.io.IOException; 11 | 12 | import javax.imageio.ImageIO; 13 | 14 | import org.junit.Test; 15 | 16 | import eu.sig.training.ch06.simpledigitalcamera.SimpleDigitalCamera; 17 | import eu.sig.training.ch10.PerfectPicture; 18 | 19 | public class PerfectPictureMockTest { 20 | // tag::testNightPictureMockito[] 21 | @Test 22 | public void testNightPictureMockito() throws IOException { 23 | BufferedImage image = 24 | ImageIO.read(new File("src/test/resources/VanGoghStarryNight.jpg")); 25 | SimpleDigitalCamera cameraMock = mock(SimpleDigitalCamera.class); 26 | PerfectPicture.camera = cameraMock; 27 | when(cameraMock.takeSnapshot()).thenReturn(image); 28 | assertEquals(image, new PerfectPicture().takePerfectPicture(0)); 29 | verify(cameraMock).flashLightOn(); 30 | } 31 | // end::testNightPictureMockito[] 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/eu/sig/training/ch10/PerfectPictureTest.java: -------------------------------------------------------------------------------- 1 | package eu.sig.training.ch10; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.awt.Image; 6 | import java.awt.image.BufferedImage; 7 | import java.io.File; 8 | import java.io.IOException; 9 | 10 | import javax.imageio.ImageIO; 11 | 12 | import org.junit.Test; 13 | 14 | import eu.sig.training.ch06.simpledigitalcamera.SimpleDigitalCamera; 15 | import eu.sig.training.ch10.PerfectPicture; 16 | 17 | public class PerfectPictureTest { 18 | 19 | // tag::testDayPicture[] 20 | @Test 21 | public void testDayPicture() throws IOException { 22 | BufferedImage image = 23 | ImageIO.read(new File("src/test/resources/VanGoghSunflowers.jpg")); 24 | DigitalCameraStub cameraStub = new DigitalCameraStub(); 25 | cameraStub.testImage = image; 26 | PerfectPicture.camera = cameraStub; 27 | assertEquals(image, new PerfectPicture().takePerfectPicture(12)); 28 | } 29 | // end::testDayPicture[] 30 | 31 | // tag::testNightPicture[] 32 | @Test 33 | public void testNightPicture() throws IOException { 34 | BufferedImage image = 35 | ImageIO.read(new File("src/test/resources/VanGoghStarryNight.jpg")); 36 | DigitalCameraMock cameraMock = new DigitalCameraMock(); 37 | cameraMock.testImage = image; 38 | PerfectPicture.camera = cameraMock; 39 | assertEquals(image, new PerfectPicture().takePerfectPicture(0)); 40 | assertEquals(1, cameraMock.flashOnCounter); 41 | } 42 | // end::testNightPicture[] 43 | 44 | } 45 | 46 | // tag::DigitalCameraStub[] 47 | class DigitalCameraStub implements SimpleDigitalCamera { 48 | public Image testImage; 49 | 50 | public Image takeSnapshot() { 51 | return this.testImage; 52 | } 53 | 54 | public void flashLightOn() {} 55 | 56 | public void flashLightOff() {} 57 | } 58 | // end::DigitalCameraStub[] 59 | 60 | // tag::DigitalCameraMock[] 61 | class DigitalCameraMock implements SimpleDigitalCamera { 62 | public Image testImage; 63 | public int flashOnCounter = 0; 64 | 65 | public Image takeSnapshot() { 66 | return this.testImage; 67 | } 68 | 69 | public void flashLightOn() { 70 | this.flashOnCounter++; 71 | } 72 | 73 | public void flashLightOff() {} 74 | } 75 | // end::DigitalCameraMock[] 76 | -------------------------------------------------------------------------------- /src/test/resources/VanGoghStarryNight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreillymedia/building_maintainable_software/4b67955ffcea790abb0a73c0a9c75153d210e51f/src/test/resources/VanGoghStarryNight.jpg -------------------------------------------------------------------------------- /src/test/resources/VanGoghSunflowers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreillymedia/building_maintainable_software/4b67955ffcea790abb0a73c0a9c75153d210e51f/src/test/resources/VanGoghSunflowers.jpg --------------------------------------------------------------------------------