depend on the
625 | // subsystem we are part of?
626 | if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))
627 | ```
628 |
629 | vs
630 |
631 | ```java
632 | ArrayList moduleDependees = smodule.getDependSubsystems();
633 | String ourSubSystem = subSysMod.getSubSystem();
634 | if (moduleDependees.contains(ourSubSystem))
635 | ```
636 |
637 | #### Position Markers
638 |
639 | This type of comments are noising
640 |
641 | ```java
642 | // Actions //////////////////////////////////
643 | ```
644 |
645 | #### Closing Brace Comments
646 |
647 | Example:
648 |
649 | ```java
650 | public class wc {
651 | public static void main(String[] args) {
652 | BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
653 | String line;
654 | int lineCount = 0;
655 | int charCount = 0;
656 | int wordCount = 0;
657 | try {
658 | while ((line = in.readLine()) != null) {
659 | lineCount++;
660 | charCount += line.length();
661 | String words[] = line.split("\\W");
662 | wordCount += words.length;
663 |
664 | } //while
665 | System.out.println("wordCount = " + wordCount);
666 | System.out.println("lineCount = " + lineCount);
667 | System.out.println("charCount = " + charCount);
668 |
669 | } // try
670 | catch (IOException e) {
671 | System.err.println("Error:" + e.getMessage());
672 |
673 | } //catch
674 |
675 | } //main
676 | ```
677 |
678 | You could break the code in small functions instead to use this type of comments.
679 |
680 | #### Attributions and Bylines
681 |
682 | Example:
683 |
684 | `/* Added by Rick */`
685 |
686 | The VCS can manage this information instead.
687 |
688 | #### Commented-Out Code
689 |
690 | ```java
691 | InputStreamResponse response = new InputStreamResponse();
692 | response.setBody(formatter.getResultStream(), formatter.getByteCount());
693 | // InputStream resultsStream = formatter.getResultStream();
694 | // StreamReader reader = new StreamReader(resultsStream);
695 | // response.setContent(reader.read(formatter.getByteCount()));
696 | ```
697 |
698 | If you don't need anymore, please delete it, you can back later with your VCS if you need it again.
699 |
700 | #### HTML Comments
701 |
702 | HTML in source code comments is an abomination, as you can tell by reading the code below.
703 |
704 | ```java
705 | /**
706 | * Task to run fit tests.
707 | * This task runs fitnesse tests and publishes the results.
708 | *
709 | *
710 | * Usage:
711 | * <taskdef name="execute-fitnesse-tests"
712 | * classname="fitnesse.ant.ExecuteFitnesseTestsTask"
713 | * classpathref="classpath" />
714 | * OR
715 | * <taskdef classpathref="classpath"
716 | * resource="tasks.properties" />
717 | *
718 | * <execute-fitnesse-tests
719 | * suitepage="FitNesse.SuiteAcceptanceTests"
720 | * fitnesseport="8082"
721 | * resultsdir="${results.dir}"
722 | * resultshtmlpage="fit-results.html"
723 | * classpathref="classpath" />
724 | *
725 | */
726 | ```
727 |
728 | #### Nonlocal Information
729 |
730 | If you must write a comment, then make sure it describes the code it appears near. Don't offer systemwide information in the context of a local comment.
731 |
732 | #### Too Much Information
733 |
734 | Don't put interesting historical discussions or irrelevant descriptions of details into your comments.
735 |
736 | #### Inobvious Connection
737 |
738 | The connection between a comment and the code it describes should be obvious. If you are going to the trouble to write a comment, then at least you'd like the reader to be able to look at the comment and the code and understand what the comment is talking about
739 |
740 | #### Function Headers
741 |
742 | Short functions don’t need much description. A well-chosen name for a small function that does one thing is usually better than a comment header.
743 |
744 | #### Javadocs in Nonpublic Code
745 |
746 | Javadocs are for public APIs, in nonpublic code could be a distraction more than a help.
747 |
748 |
749 | Chapter 5 - Formatting
750 |
751 |
752 | Code formatting is important. It is too important to ignore and it is too important to treat religiously. Code formatting is about communication, and communication is the professional developer’s first order of business.
753 |
754 | ### Vertical Formatting
755 |
756 | #### Vertical Openness Between Concepts
757 |
758 | This concept consist in how to you separate concepts in your code, In the next example we can appreciate it.
759 |
760 | ```java
761 | package fitnesse.wikitext.widgets;
762 |
763 | import java.util.regex.*;
764 |
765 | public class BoldWidget extends ParentWidget {
766 | public static final String REGEXP = "'''.+?'''";
767 | private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
768 | Pattern.MULTILINE + Pattern.DOTALL
769 | );
770 |
771 | public BoldWidget(ParentWidget parent, String text) throws Exception {
772 | super(parent);
773 | Matcher match = pattern.matcher(text);
774 | match.find();
775 | addChildWidgets(match.group(1));
776 | }
777 |
778 | public String render() throws Exception {
779 | StringBuffer html = new StringBuffer("");
780 | html.append(childHtml()).append("");
781 | return html.toString();
782 | }
783 | }
784 | ```
785 |
786 | ```java
787 | package fitnesse.wikitext.widgets;
788 | import java.util.regex.*;
789 | public class BoldWidget extends ParentWidget {
790 | public static final String REGEXP = "'''.+?'''";
791 | private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
792 | Pattern.MULTILINE + Pattern.DOTALL);
793 | public BoldWidget(ParentWidget parent, String text) throws Exception {
794 | super(parent);
795 | Matcher match = pattern.matcher(text); match.find(); addChildWidgets(match.group(1));
796 | }
797 | public String render() throws Exception { StringBuffer html = new StringBuffer(""); html.append(childHtml()).append(""); return html.toString();
798 | }
799 | }
800 | ```
801 |
802 | As you can see, the readability of the first example is greater than that of the second.
803 |
804 | #### Vertical Density
805 |
806 | The vertical density implies close association. So lines of code that are tightly related should appear vertically dense. Check the follow example:
807 |
808 | ```Java
809 | public class ReporterConfig {
810 |
811 | /**
812 | * The class name of the reporter listener */
813 | private String m_className;
814 |
815 | /**
816 | * The properties of the reporter listener */
817 | private List m_properties = new ArrayList();
818 |
819 | public void addProperty(Property property) { m_properties.add(property);
820 | }
821 | ```
822 |
823 | ```java
824 | public class ReporterConfig {
825 | private String m_className;
826 | private List m_properties = new ArrayList();
827 |
828 | public void addProperty(Property property) {
829 | m_properties.add(property);
830 | }
831 | }
832 | ```
833 |
834 | The second code it's much easier to read. It fits in an "eye-full".
835 |
836 | #### Vertical Distance
837 |
838 | **Variable Declarations**. Variables should be declared as close to their usage as possible. Because our functions are very short, local variables should appear at the top of each function,
839 |
840 | **Instance variables**, on the other hand, should be declared at the top of the class. This should not increase the vertical distance of these variables, because in a well-designed class, they are used by many, if not all, of the methods of the class.
841 |
842 | There have been many debates over where instance variables should go. In C++ we commonly practiced the so-called scissors rule, which put all the instance variables at the bottom. The common convention in Java, however, is to put them all at the top of the class. I see no reason to follow any other convention. The important thing is for the instance variables to be declared in one well-known place. Everybody should know where to go to see the declarations.
843 |
844 | **Dependent Functions**. If one function calls another, they should be vertically close, and the caller should be above the callee, if at all possible. This gives the program a natural flow. If the convention is followed reliably, readers will be able to trust that function definitions will follow shortly after their use.
845 |
846 | **Conceptual Affinity**. Certain bits of code want to be near other bits. They have a certain conceptual affinity. The stronger that affinity, the less vertical distance there should be between them.
847 |
848 | #### Vertical Ordering
849 |
850 | In general we want function call dependencies to point in the downward direction. That is, a function that is called should be below a function that does the calling. This creates a nice flow down the source code module from high level to low level. _(This is the exact opposite of languages like Pascal, C, and C++ that enforce functions to be defined, or at least declared, before they are used)_
851 |
852 | ### Horizontal Formatting
853 |
854 | #### Horizontal Openness and Density
855 |
856 | We use horizontal white space to associate things that are strongly related and disassociate things that are more weakly related. Example:
857 |
858 | ```java
859 | private void measureLine(String line) {
860 | lineCount++;
861 | int lineSize = line.length();
862 | totalChars += lineSize;
863 | lineWidthHistogram.addLine(lineSize, lineCount);
864 | recordWidestLine(lineSize);
865 | }
866 | ```
867 |
868 | Assignment statements have two distinct and major elements: the left side and the right side. The spaces make that separation obvious.
869 |
870 | #### Horizontal Alignment
871 |
872 | ```java
873 | public class Example implements Base
874 | {
875 | private Socket socket;
876 | private inputStream input;
877 | protected long requestProgress;
878 |
879 | public Expediter(Socket s,
880 | inputStream input) {
881 | this.socket = s;
882 | this.input = input;
883 | }
884 | }
885 | ```
886 |
887 | In modern languages this type of alignment is not useful. The alignment seems to emphasize the wrong things and leads my eye away from the true intent.
888 |
889 | ```java
890 | public class Example implements Base
891 | {
892 | private Socket socket;
893 | private inputStream input;
894 | protected longrequestProgress;
895 |
896 | public Expediter(Socket s, inputStream input) {
897 |
898 | this.socket = s;
899 | this.input = input;
900 | }
901 | }
902 | ```
903 |
904 | This is a better approach.
905 |
906 | ### Indentation
907 |
908 | The indentation it's important because help us to have a visible hierarchy and well defined blocks.
909 |
910 | ### Team Rules
911 |
912 | Every programmer has his own favorite formatting rules, but if he works in a team, then the team rules.
913 |
914 | A team of developers should agree upon a single formatting style, and then every member of that team should use that style. We want the software to have a consistent style. We don't want it to appear to have been written by a bunch of disagreeing individuals.
915 |
916 |
917 | Chapter 6 - Objects and Data Structures
918 |
919 |
920 | ### Data Abstraction
921 |
922 | Hiding implementation is not just a matter of putting a layer of functions between the variables. Hiding implementation is about abstractions! A class does not simply push its variables out through getters and setters. Rather it exposes abstract interfaces that allow its users to manipulate the essence of the data, without having to know its implementation.
923 |
924 | ### Data/Object Anti-Symmetry
925 |
926 | These two examples show the difference between objects and data structures. Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions.
927 |
928 | **Procedural Shape**
929 |
930 | ```java
931 | public class Square {
932 | public Point topLeft;
933 | public double side;
934 | }
935 |
936 | public class Rectangle {
937 | public Point topLeft;
938 | public double height;
939 | public double width;
940 | }
941 |
942 | public class Circle {
943 | public Point center;
944 | public double radius;
945 | }
946 |
947 | public class Geometry {
948 | public final double PI = 3.141592653589793;
949 |
950 | public double area(Object shape) throws NoSuchShapeException {
951 | if (shape instanceof Square) {
952 | Square s = (Square)shape;
953 | return s.side * s.side;
954 | }
955 | else if (shape instanceof Rectangle) { Rectangle r = (Rectangle)shape; return r.height * r.width;
956 | }
957 | else if (shape instanceof Circle) {
958 | Circle c = (Circle)shape;
959 | return PI * c.radius * c.radius;
960 | }
961 | throw new NoSuchShapeException();
962 | }
963 | }
964 | ```
965 |
966 | **Polymorphic Shape**
967 |
968 | ```java
969 | public class Square implements Shape {
970 | private Point topLeft;
971 | private double side;
972 |
973 | public double area() {
974 | return side*side;
975 | }
976 | }
977 |
978 | public class Rectangle implements Shape {
979 | private Point topLeft;
980 | private double height;
981 | private double width;
982 |
983 | public double area() {
984 | return height * width;
985 | }
986 | }
987 |
988 | public class Circle implements Shape {
989 | private Point center;
990 | private double radius;
991 | public final double PI = 3.141592653589793;
992 |
993 | public double area() {
994 | return PI * radius * radius;
995 | }
996 | }
997 | ```
998 |
999 | Again, we see the complimentary nature of these two definitions; they are virtual opposites! This exposes the fundamental dichotomy between objects and data structures:
1000 |
1001 | > Procedural code (code using data structures) makes it easy to add new functions without changing the existing data structures. OO code, on the other hand, makes it easy to add new classes without changing existing functions.
1002 |
1003 | The complement is also true:
1004 |
1005 | > Procedural code makes it hard to add new data structures because all the functions must change. OO code makes it hard to add new functions because all the classes must change.
1006 |
1007 | Mature programmers know that the idea that everything is an object is a myth. Sometimes you really do want simple data structures with procedures operating on them.
1008 |
1009 | ### The Law of [Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter)
1010 |
1011 | There is a well-known heuristic called the Law of Demeter that says a module should not know about the innards of the objects it manipulates.
1012 |
1013 | More precisely, the Law of Demeter says that a method `f` of a class `C` should only call the methods of these:
1014 |
1015 | - `C`
1016 | - An object created by `f`
1017 | - An object passed as an argument to `f`
1018 | - An object held in an instance variable of `C`
1019 |
1020 | The method should not invoke methods on objects that are returned by any of the allowed functions. In other words, talk to friends, not to strangers.
1021 |
1022 | ### Data Transfer Objects
1023 |
1024 | The quintessential form of a data structure is a class with public variables and no functions. This is sometimes called a data transfer object, or DTO. DTOs are very useful structures, especially when communicating with databases or parsing messages from sockets, and so on. They often become the first in a series of translation stages that convert raw data in a database into objects in the application code.
1025 |
1026 |
1027 | Chapter 7 - Error Handling
1028 |
1029 |
1030 | Many code bases are completely dominated by error handling. When I say dominated, I don't mean that error handling is all that they do. I mean that it is nearly impossible to see what the code does because of all of the scattered error handling. Error handling is important, but if it obscures logic, it's wrong.
1031 |
1032 | ### Use Exceptions Rather Than Return Codes
1033 |
1034 | Back in the distant past there were many languages that didn't have exceptions. In those languages the techniques for handling and reporting errors were limited. You either set an error flag or returned an error code that the caller could check
1035 |
1036 | ### Write Your Try-Catch-Finally Statement First
1037 |
1038 | In a way, try blocks are like transactions. Your catch has to leave your program in a consistent state, no matter what happens in the try. For this reason it is good practice to start with a try-catch-finally statement when you are writing code that could throw exceptions. This helps you define what the user of that code should expect, no matter what goes wrong with the code that is executed in the try.
1039 |
1040 | ### Provide Context with Exceptions
1041 |
1042 | Each exception that you throw should provide enough context to determine the source and location of an error.
1043 |
1044 | Create informative error messages and pass them along with your exceptions. Mention the operation that failed and the type of failure. If you are logging in your application, pass along enough information to be able to log the error in your catch.
1045 |
1046 | ### Don't Return Null
1047 |
1048 | If you are tempted to return null from a method, consider throwing an exception or returning a SPECIAL CASE object instead. If you are calling a null-returning method from a third-party API, consider wrapping that method with a method that either throws an exception or returns a special case object.
1049 |
1050 | ### Don't Pass Null
1051 |
1052 | Returning null from methods is bad, but passing null into methods is worse. Unless you are working with an API which expects you to pass null, you should avoid passing null in your code whenever possible.
1053 |
1054 |
1055 | Chapter 8 - Boundaries
1056 |
1057 |
1058 | We seldom control all the software in our systems. Sometimes we buy third-party pack- ages or use open source. Other times we depend on teams in our own company to produce components or subsystems for us. Somehow we must cleanly integrate this foreign code with our own.
1059 |
1060 | ### Using Third-Party Code
1061 |
1062 | There is a natural tension between the provider of an interface and the user of an interface. Providers of third-party packages and frameworks strive for broad applicability so they can work in many environments and appeal to a wide audience. Users, on the other hand, want an interface that is focused on their particular needs. This tension can cause problems at the boundaries of our systems. Example:
1063 |
1064 | ```java
1065 | Map sensors = new HashMap();
1066 | Sensor s = (Sensor)sensors.get(sensorId);
1067 | ```
1068 |
1069 | VS
1070 |
1071 | ```java
1072 | public class Sensors {
1073 | private Map sensors = new HashMap();
1074 |
1075 | public Sensor getById(String id) {
1076 | return (Sensor) sensors.get(id);
1077 | }
1078 | //snip
1079 | }
1080 | ```
1081 |
1082 | The first code exposes the casting in the Map, while the second is able to evolve with very little impact on the rest of the application. The casting and type management is handled inside the Sensors class.
1083 |
1084 | The interface is also tailored and constrained to meet the needs of the application. It results in code that is easier to understand and harder to misuse. The Sensors class can enforce design and business rules.
1085 |
1086 | ### Exploring and Learning Boundaries
1087 |
1088 | Third-party code helps us get more functionality delivered in less time. Where do we start when we want to utilize some third-party package? It’s not our job to test the third-party code, but it may be in our best interest to write tests for the third-party code we use.
1089 |
1090 | It's a good idea write some test for learn and understand how to use a third-party code. Newkirk calls such tests learning tests.
1091 |
1092 | ### Learning Tests Are Better Than Free
1093 |
1094 | The learning tests end up costing nothing. We had to learn the API anyway, and writing those tests was an easy and isolated way to get that knowledge. The learning tests were precise experiments that helped increase our understanding.
1095 |
1096 | Not only are learning tests free, they have a positive return on investment. When there are new releases of the third-party package, we run the learning tests to see whether there are behavioral differences.
1097 |
1098 | ### Using Code That Does Not Yet Exist
1099 |
1100 | Some times it's necessary work in a module that will be connected to another module under develop, and we have no idea about how to send the information, because the API had not been designed yet. In this cases it's recommendable create an interface for encapsulate the communication with the pending module. In this way we maintain the control over our module and we can test although the second module isn't available yet.
1101 |
1102 | ### Clean Boundaries
1103 |
1104 | Interesting things happen at boundaries. Change is one of those things. Good software designs accommodate change without huge investments and rework. When we use code that is out of our control, special care must be taken to protect our investment and make sure future change is not too costly.
1105 |
1106 |
1107 | Chapter 9 - Unit Tests
1108 |
1109 |
1110 | **T**est
1111 | **D**riven
1112 | **D**evelopment
1113 |
1114 | ### The Three Laws of TDD
1115 |
1116 | - **First Law** You may not write production code until you have written a failing unit test.
1117 | - **Second Law** You may not write more of a unit tests than is sufficient to fail, and not comipling is failing.
1118 | - **Third Law** You may not write more production code than is sufficient to pass the currently failing tests.
1119 |
1120 | ### Clean Tests
1121 |
1122 | If you don't keep your tests clean, you will lose them.
1123 |
1124 | The readability it's very important to keep clean your tests.
1125 |
1126 | ### One Assert per test
1127 |
1128 | It's recomendable maintain only one asserts per tests, because this helps to maintain each tests easy to understand.
1129 |
1130 | ### Single concept per Test
1131 |
1132 | This rule will help you to keep short functions.
1133 |
1134 | - **Write one test per each concept that you need to verify**
1135 |
1136 | ### F.I.R.S.T
1137 |
1138 | - **Fast** Test should be fast.
1139 | - **Independient** Test should not depend on each other.
1140 | - **Repeatable** Test Should be repeatable in any environment.
1141 | - **Self-Validating** Test should have a boolean output. either they pass or fail.
1142 | - **Timely** Unit tests should be written just before the production code that makes them pass. If you write tests after the production code, then you may find the production code to be hard to test.
1143 |
1144 |
1145 | Chapter 10 - Classes
1146 |
1147 |
1148 | ## Class Organization
1149 |
1150 | ### Encapsulation
1151 |
1152 | We like to keep our variables and utility functions small, but we're not fanatic about it. Sometimes we need to make a variable or utility function protected so that it can be accessed by a test.
1153 |
1154 | ## Classes Should be Small
1155 |
1156 | - First Rule: Classes should be small
1157 | - Second Rule: **Classes should be smaller than the first rule**
1158 |
1159 | ### The Single Responsibility Principle
1160 |
1161 | **Classes should have one responsibility - one reason to change**
1162 |
1163 | SRP is one of the more important concept in OO design. It's also one of the simple concepts to understand and adhere to.
1164 |
1165 | ### Cohesion
1166 |
1167 | Classes Should have a small number of instance variables. Each of the methods of a class should manipulate one or more of those variables. In general the more variables a method manipulates the more cohesive that method is to its class. A class in which each variable is used by each method is maximally cohesive.
1168 |
1169 | ### Maintaining Cohesion Results in Many Small Classes
1170 |
1171 | Just the act of breaking large functions into smaller functions causes a proliferation of classes.
1172 |
1173 | ## Organizing for change
1174 |
1175 | For most systems, change is continual. Every change subjects us to the risk that the remainder of the system no longer works as intended. In a clean system we organize our classes so as to reduce the risk of change.
1176 |
1177 | ### Isolating from Change
1178 |
1179 | Needs will change, therefore code will change. We learned in OO 101 that there are concrete classes, which contain implementation details (code), and abstract classes, which represent concepts only. A client class depending upon concrete details is at risk when those details change. We can introduce intefaces and abstract classes to help isolate the impact of those details.
1180 |
1181 |
1182 | Chapter 11 - Systems
1183 |
1184 |
1185 | ## Separe Constructing a System from using It
1186 |
1187 | _Software Systems should separate the startuo process, when the application objects are constructed and the dependencies are "wired" thogether, from the runtime logic that takes over after startup_
1188 |
1189 | ### Separation from main
1190 |
1191 | One way to separate construction from use is simply to move all aspects of construction to `main`, or modules called by `main`, and to design the rest of the system assuming that all objects have been created constructed and wired up appropriately.
1192 |
1193 | The Abstract Factory Pattern is an option for this kind of approach.
1194 |
1195 | ### Dependency Injection
1196 |
1197 | A powerful mechanism for separating construction from use is Dependency Injection (DI), the application of Inversion of control (IoC) to dependency management. Inversion of control moves secondary responsibilities from an object to other objects that are dedicated to the purpose, thereby supporting the Single Responsibility Principle. In context of dependency management, an object should not take responsibility for instantiating dependencies itself. Instead, it, should pass this responsibility to another "authoritative" mechanism, thereby inverting the control. Because setup is a global concern, this authoritative mechanism will usually be either the "main"
1198 | routine or a special-purpose _container_.
1199 |
1200 |
1201 | Chapter 12 - Emergence
1202 |
1203 |
1204 | According to Kent Beck, a design is "simple" if it follows these rules
1205 |
1206 | - Run all tests
1207 | - Contains no duplication
1208 | - Expresses the intent of programmers
1209 | - Minimizes the number of classes and methods
1210 |
1211 |
1212 | Chapter 13 - Concurrency
1213 |
1214 |
1215 | Concurrence is a decoupling strategy. It helps us decouple what gets fone from when it gets done. In single-threaded applications what and when are so strongly coupled that the state of the entire application can often be determined by looking at the stack backtrace. A programmer who debugs such a system can set a breakpoint, or a sequence of breakpoints, and know the state of the system by which breakpoints are hit.
1216 |
1217 | Decoupling what from when can dramatically improve both the throughput and structures of an application. From a structural point of view the application looks like many lit- tle collaborating computers rather than one big main loop. This can make the system easier to understand and offers some powerful ways to separate concerns.
1218 |
1219 | ## Miths and Misconceptions
1220 |
1221 | - Concurrency always improves performance.
1222 | Concurrency can sometimes improve performance, but only when there is a lot of wait time that can be shared between multiple threads or multiple processors. Neither situ- ation is trivial.
1223 | - Design does not change when writing concurrent programs.
1224 | In fact, the design of a concurrent algorithm can be remarkably different from the design of a single-threaded system. The decoupling of what from when usually has a huge effect on the structure of the system.
1225 | - Understanding concurrency issues is not important when working with a container such as a Web or EJB container.
1226 | In fact, you’d better know just what your container is doing and how to guard against the issues of concurrent update and deadlock described later in this chapter.
1227 | Here are a few more balanced sound bites regarding writing concurrent software:
1228 | - Concurrency incurs some overhead, both in performance as well as writing additional code.
1229 | - Correct concurrency is complex, even for simple problems.
1230 | - Concurrency bugs aren’t usually repeatable, so they are often ignored as one-offs instead of the true defects they are.
1231 | - Concurrency often requires a fundamental change in design strategy.
1232 |
1233 | #
1234 |
1235 |
1236 | Chapter 14 - Successive Refinement
1237 |
1238 | This chapter is a study case. It's recommendable to completely read it to understand more.
1239 |
1240 |
1241 | Chapter 15 - JUnit Internals
1242 |
1243 | This chapter analize the JUnit tool. It's recommendable to completely read it to understand more.
1244 |
1245 |
1246 | Chapter 16 - Refactoring SerialDate
1247 |
1248 | This chapter is a study case. It's recommendable to completely read it to understand more.
1249 |
1250 |
1251 | Chapter 17 - Smells and Heuristics
1252 |
1253 |
1254 | A reference of code smells from Martin Fowler's _Refactoring_ and Robert C Martin's _Clean Code_.
1255 |
1256 | While clean code comes from discipline and not a list or value system, here is a starting point.
1257 |
1258 | ## Comments
1259 |
1260 | #### C1: Inappropriate Information
1261 |
1262 | Reserve comments for technical notes referring to code and design.
1263 |
1264 | #### C2: Obsolete Comment
1265 |
1266 | Update or delete obsolete comments.
1267 |
1268 | #### C3: Redundant Comment
1269 |
1270 | A redundant comment describes something able to sufficiently describe itself.
1271 |
1272 | #### C4: Poorly Written Comment
1273 |
1274 | Comments should be brief, concise, correctly spelled.
1275 |
1276 | #### C5: Commented-Out Code
1277 |
1278 | Ghost code. Delete it.
1279 |
1280 | ## Environment
1281 |
1282 | #### E1: Build Requires More Than One Step
1283 |
1284 | Builds should require one command to check out and one command to run.
1285 |
1286 | #### E2: Tests Require More Than One Step
1287 |
1288 | Tests should be run with one button click through an IDE, or else with one command.
1289 |
1290 | ## Functions
1291 |
1292 | #### F1: Too Many Arguments
1293 |
1294 | Functions should have no arguments, then one, then two, then three. No more than three.
1295 |
1296 | #### F2: Output Arguments
1297 |
1298 | Arguments are inputs, not outputs. If somethings state must be changed, let it be the state of the called object.
1299 |
1300 | #### F3: Flag Arguments
1301 |
1302 | Eliminate boolean arguments.
1303 |
1304 | #### F4: Dead Function
1305 |
1306 | Discard uncalled methods. This is dead code.
1307 |
1308 | ## General
1309 |
1310 | #### G1: Multiple Languages in One Source File
1311 |
1312 | Minimize the number of languages in a source file. Ideally, only one.
1313 |
1314 | #### G2: Obvious Behavior is Unimplemented
1315 |
1316 | The result of a function or class should not be a surprise.
1317 |
1318 | #### G3: Incorrect Behavior at the Boundaries
1319 |
1320 | Write tests for every boundary condition.
1321 |
1322 | #### G4: Overridden Safeties
1323 |
1324 | Overriding safeties and exerting manual control leads to code melt down.
1325 |
1326 | #### G5: Duplication
1327 |
1328 | Practice abstraction on duplicate code. Replace repetitive functions with polymorphism.
1329 |
1330 | #### G6: Code at Wrong Level of Abstraction
1331 |
1332 | Make sure abstracted code is separated into different containers.
1333 |
1334 | #### G7: Base Classes Depending on Their Derivatives
1335 |
1336 | Practice modularity.
1337 |
1338 | #### G8: Too Much Information
1339 |
1340 | Do a lot with a little. Limit the amount of _things_ going on in a class or functions.
1341 |
1342 | #### G9: Dead Code
1343 |
1344 | Delete unexecuted code.
1345 |
1346 | #### G10: Vertical Separation
1347 |
1348 | Define variables and functions close to where they are called.
1349 |
1350 | #### G11: Inconsistency
1351 |
1352 | Choose a convention, and follow it. Remember no surprises.
1353 |
1354 | #### G12: Clutter
1355 |
1356 | Dead code.
1357 |
1358 | #### G13: Artificial Coupling
1359 |
1360 | Favor code that is clear, rather than convenient. Do not group code that favors mental mapping over clearness.
1361 |
1362 | #### G14: Feature Envy
1363 |
1364 | Methods of one class should not be interested with the methods of another class.
1365 |
1366 | #### G15: Selector Arguments
1367 |
1368 | Do not flaunt false arguments at the end of functions.
1369 |
1370 | #### G16: Obscured Intent
1371 |
1372 | Code should not be magic or obscure.
1373 |
1374 | #### G17: Misplaced Responsibility
1375 |
1376 | Use clear function name as waypoints for where to place your code.
1377 |
1378 | #### G18: Inappropriate Static
1379 |
1380 | Make your functions nonstatic.
1381 |
1382 | #### G19: Use Explanatory Variables
1383 |
1384 | Make explanatory variables, and lots of them.
1385 |
1386 | #### G20: Function Names Should Say What They Do
1387 |
1388 | ...
1389 |
1390 | #### G21: Understand the Algorithm
1391 |
1392 | Understand how a function works. Passing tests is not enough. Refactoring a function can lead to a better understanding of it.
1393 |
1394 | #### G22: Make Logical Dependencies Physical
1395 |
1396 | Understand what your code is doing.
1397 |
1398 | #### G23: Prefer Polymorphism to If/Else or Switch/Case
1399 |
1400 | Avoid the brute force of switch/case.
1401 |
1402 | #### G24: Follow Standard Conventions
1403 |
1404 | It doesn't matter what your teams convention is. Just that you have on and everyone follows it.
1405 |
1406 | #### G25: Replace Magic Numbers with Named Constants
1407 |
1408 | Stop spelling out numbers.
1409 |
1410 | #### G26: Be Precise
1411 |
1412 | Don't be lazy. Think of possible results, then cover and test them.
1413 |
1414 | #### G27: Structure Over Convention
1415 |
1416 | Design decisions should have a structure rather than a dogma.
1417 |
1418 | #### G28: Encapsulate Conditionals
1419 |
1420 | Make your conditionals more precise.
1421 |
1422 | #### G29: Avoid Negative Conditionals
1423 |
1424 | Negative conditionals take more brain power to understand than a positive.
1425 |
1426 | #### G31: Hidden Temporal Couplings
1427 |
1428 | Use arguents that make temporal coupling explicit.
1429 |
1430 | #### G32: Don’t Be Arbitrary
1431 |
1432 | Your code's sturcture should communicate the reason for its structure.
1433 |
1434 | #### G33: Encapsulate Boundary Conditions
1435 |
1436 | Avoid leaking +1's and -1's into your code.
1437 |
1438 | #### G34: Functions Should Descend Only One Level of Abstraction
1439 |
1440 | The toughest heuristic to follow. One level of abstraction below the function's described operation can help clarify your code.
1441 |
1442 | #### G35: Keep Configurable Data at High Levels
1443 |
1444 | High level constants are easy to change.
1445 |
1446 | #### G36: Avoid Transitive Navigation
1447 |
1448 | Write shy code. Modules should only know about their neighbors, not their neighbor's neighbors.
1449 |
1450 | ## Names
1451 |
1452 | #### N1: Choose Descriptive Names
1453 |
1454 | Choose names that are descriptive and relevant.
1455 |
1456 | #### N2: Choose Names at the Appropriate Level of Abstraction
1457 |
1458 | Think of names that are still clear to the user when used in different programs.
1459 |
1460 | #### N3: Use Standard Nomenclature Where Possible
1461 |
1462 | Use names that express their task.
1463 |
1464 | #### N4: Unambiguous Names
1465 |
1466 | Favor clearness over curtness. A long, expressive name is better than a short, dull one.
1467 |
1468 | #### N5: Use Long Names for Long Scopes
1469 |
1470 | A name's length should relate to its scope.
1471 |
1472 | #### N6: Avoid Encodings
1473 |
1474 | No not encode names with type or scope information.
1475 |
1476 | #### N7: Names Should Describe Side-Effects
1477 |
1478 | Consider the side-effects of your function, and include that in its name.
1479 |
1480 | ## Tests
1481 |
1482 | #### T1: Insufficient Tests
1483 |
1484 | Test everything that can possibly break
1485 |
1486 | #### T2: Use a Coverage Tool!
1487 |
1488 | Use your IDE as a coverage tool.
1489 |
1490 | #### T3: Don’t Skip Trivial Tests
1491 |
1492 | ...
1493 |
1494 | #### T4: An Ignored Test is a Question about an Ambiguity
1495 |
1496 | If your test is ignored, the code is brought into question.
1497 |
1498 | #### T5: Test Boundary Conditions
1499 |
1500 | The middle is usually covered. Remember the boundaries.
1501 |
1502 | #### T6: Exhaustively Test Near Bugs
1503 |
1504 | Bugs are rarely alone. When you find one, look nearby for another.
1505 |
1506 | #### T7: Patterns of Failure Are Revealing
1507 |
1508 | Test cases ordered well will reveal patterns of faiure.
1509 |
1510 | #### T8: Test Coverage Patterns Can Be Revealing
1511 |
1512 | Similarly, look at the code that is or is not passed in a failure.
1513 |
1514 | #### T9: Tests Should Be Fast
1515 |
1516 | Slow tests won't get run.
1517 |
--------------------------------------------------------------------------------