diff --git a/Temporary b/AndroidTestingStandard.md similarity index 87% rename from Temporary rename to AndroidTestingStandard.md index 81877d7..c76cb68 100644 --- a/Temporary +++ b/AndroidTestingStandard.md @@ -1,4 +1,4 @@ -# Android Coding Standard +# Android Testing Standard ### 2.4 Test style rules @@ -14,8 +14,10 @@ Any Unit Test classes should be written to match the name of the class that the All Test methods should be annotated with the `@Test` annotation, the methods should be named using the following template: +```java @Test public void methodNamePreconditionExpectedResult() { } +``` So for example, if we want to check that the signUp() method with an invalid email address fails, the test would look like: @@ -26,9 +28,11 @@ Tests should focus on testing only what the method name entitles, if there’s e If a class we are testing contains many different methods, then the tests should be split across multiple test classes - this helps to keep the tests more maintainable and easier to locate. For example, a DatabaseHelper class may need to be split into multiple test classes such as : +```java DatabaseHelperUserTest DatabaseHelperPostsTest DatabaseHelperDraftsTest +``` #### 2.4.2 Espresso tests @@ -42,23 +46,21 @@ Each Espresso test class generally targets an Activity, so the name given to it When using the Espresso API, methods should be chained on new lines to make the statements more readable, for example: +```java onView(withId(R.id.text_title)) .perform(scrollTo()) .check(matches(isDisplayed())) +``` -Chaining calls in this style not only helps us stick to less than 100 characters per line but it also makes it easy to read the chain of events taking place in espresso tests. +Chaining calls in this style not only helps us stick to less than 100 characters per line but it also makes it easy to read the chain of events taking place in Espresso tests. ## 3. Being consistent -Our parting thought: BE CONSISTENT. If you're edition code, take a few minutes to look at the code around you and determine its style. If they use spaces around if clauses, you should too. If their comments have little boxes of stars around them, make your comments have little boxes of stars around them too. +Our parting thought: BE CONSISTENT. If you're editing code, take a few minutes to look at the code around you and determine its style. If they use spaces around if clauses, you should too. If their comments have little boxes of stars around them, make your comments have little boxes of stars around them too. -The point of having style guidelines is to have a common vocabulary of coding, so people can concentrate on what you're saying, rather than on how you're saying it. We present global style rules here so people know the vocabulary. But local style is also important. If code you add to a file looks drastically different from the existing code around it, it throws readers our of their rhythm when they to to read it. +The point of having style guidelines is to have a common vocabulary of coding, so people can concentrate on what you're saying, rather than on how you're saying it. We present global style rules here so people know the vocabulary. But local style is also important. If code you add to a file looks drastically different from the existing code around it, it throws readers out of their rhythm when they try to read it. -### 4.2 MVP Architecture - -A brief case study for the Model View Presenter (MVP) Architecture while we were developing apps for the Android Platform is described [here] (https://gist.github.com/grishmashrestha/cefe04eeaf74091fb80d66d6c13631b1). - -## 5. Sources +## 4. Sources - https://github.com/futurice/android-best-practices#gradle-configuration (Prefer to follow this) - https://lftechnology.atlassian.net/wiki/display/AS/Android+Station - https://github.com/bufferapp/android-guidelines/blob/master/project_style_guidelines.md diff --git a/Gradle.md b/Gradle.md index e1be103..e6a6cb5 100644 --- a/Gradle.md +++ b/Gradle.md @@ -8,23 +8,23 @@ _Don't do this_. This would appear in the version control system. ```groovy -signingConfigs { - release { - storeFile file("myapp.keystore") - storePassword "password123" - keyAlias "thekey" - keyPassword "password789" + signingConfigs { + release { + storeFile file("myapp.keystore") + storePassword "password123" + keyAlias "thekey" + keyPassword "password789" + } } -} ``` Instead, make a `keystore.properties` file which should _not_ be added to the version control system: ``` -storePassword=test123 -keyPassword=test1234 -keyAlias=sch -storeFile=/Users/ayush/sch.keystore + storePassword=test123 + keyPassword=test1234 + keyAlias=sch + storeFile=/Users/ayush/sch.keystore ``` To import the properties for build configuration follow the steps listed below: @@ -32,21 +32,21 @@ To import the properties for build configuration follow the steps listed below: i. In your module's build.gradle file, add code to load your keystore.properties file before the android {} block. ```groovy -... + ... -// Create a variable called keystorePropertiesFile, and initialize it to your -// keystore.properties file, in the rootProject folder. -def keystorePropertiesFile = rootProject.file("keystore.properties") + // Create a variable called keystorePropertiesFile, and initialize it to your + // keystore.properties file, in the rootProject folder. + def keystorePropertiesFile = rootProject.file("keystore.properties") -// Initialize a new Properties() object called keystoreProperties. -def keystoreProperties = new Properties() + // Initialize a new Properties() object called keystoreProperties. + def keystoreProperties = new Properties() -// Load your keystore.properties file into the keystoreProperties object. -keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + // Load your keystore.properties file into the keystoreProperties object. + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) -android { - ... -} + android { + ... + } ``` Note: You could choose to store your keystore.properties file in another location (for example, in the module folder rather than the root folder for the project, or on your build server if you are using a continuous integration tool). In that case, you should modify the code above to correctly initialize keystorePropertiesFile using your actual keystore.properties file's location. @@ -54,15 +54,15 @@ Note: You could choose to store your keystore.properties file in another locatio ii. You can refer to properties stored in `keystoreProperties` using the syntax `keystoreProperties['propertyName']`. Modify the `signingConfigs` block of your module's `build.gradle` file to reference the signing information stored in keystoreProperties using this syntax. ```groovy -android { - signingConfigs { - config { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile file(keystoreProperties['storeFile']) - storePassword keystoreProperties['storePassword'] + android { + signingConfigs { + config { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile file(keystoreProperties['storeFile']) + storePassword keystoreProperties['storePassword'] + } } + ... } - ... - } ``` diff --git a/JavaGuidelines.md b/JavaGuidelines.md index 08e0ea2..05c7880 100644 --- a/JavaGuidelines.md +++ b/JavaGuidelines.md @@ -15,7 +15,7 @@ A source file consists of, in order: Because we use Android Studio, so imports should always be ordered automatically. However, in the case that they may not be, then they should be ordered as follows: -1. Android imports +1. Android imports 2. Imports from third parties 3. java and javax imports 4. Imports from the current Project @@ -88,57 +88,57 @@ To improve code readability, it’s important to organise class members in a log For example: ```java - public class MainActivity extends Activity { +public class MainActivity extends Activity { - private int count; + private int count; - public static newInstance() { } + public static newInstance() { } - @Override - public void onCreate() { } + @Override + public void onCreate() { } - public setUsername() { } + public setUsername() { } - private void setupUsername() { } + private void setupUsername() { } - static class AnInnerClass { } + static class AnInnerClass { } - interface SomeInterface { } + interface SomeInterface { } - } +} ``` Any lifecycle methods used in Android framework classes should be ordered in the corresponding lifecycle order. For example: ```java - public class MainActivity extends Activity { +public class MainActivity extends Activity { - // Field and constructors + // Field and constructors - @Override - public void onCreate() { } + @Override + public void onCreate() { } - @Override - public void onStart() { } + @Override + public void onStart() { } - @Override - public void onResume() { } + @Override + public void onResume() { } - @Override - public void onPause() { } + @Override + public void onPause() { } - @Override - public void onStop() { } + @Override + public void onStop() { } - @Override - public void onRestart() { } + @Override + public void onRestart() { } - @Override - public void onDestroy() { } + @Override + public void onDestroy() { } - // public methods, private methods, inner classes and interfaces + // public methods, private methods, inner classes and interfaces - } +} ``` **Note:** @@ -169,7 +169,7 @@ For classes that extend an Android component, the name of the class should end w All fields should be declared at the top of the file, following these rules: -- Private, non-static field names should not start with m. This is right: +Private, non-static field names should not start with m. This is right: `userSignedIn`, `userNameText`, `acceptButton` @@ -182,28 +182,29 @@ Private, static field names do not need to start with an s. This is right: `someStaticField`, `userNameText` Not this: + `sSomeStaticField`, `sUserNameText` -- All other fields also start with a lower case letter. +All other fields also start with a lower case letter: ```java - int numOfChildren; - String username; + int numOfChildren; + String username; ``` -- Static final fields (known as constants) are ALL_CAPS_WITH_UNDERSCORES. +Static final fields (known as constants) are ALL_CAPS_WITH_UNDERSCORES: ```java - private static final int PAGE_COUNT = 0; + private static final int PAGE_COUNT = 0; ``` -Field names that do not reveal intention should not be used. For example, +Field names that do not reveal intention should not be used. For example: ```java int e; //number of elements in the list ``` -why not just give the field a meaningful name in the first place, rather than leaving a comment! +Why not just give the field a meaningful name in the first place, rather than leaving a comment? ```java int numberOfElements; @@ -242,7 +243,7 @@ If and when container names change in the future, the naming of these can often #### Avoid similar naming -Naming variables, method and / or classes with similar names can make it confusing for other developers reading over your code. For example: +Naming variables, method and/or classes with similar names can make it confusing for other developers reading over your code. For example: ``` hasUserSelectedSingleProfilePreviously @@ -266,7 +267,7 @@ It's hard to understand what these parameters do without reading the code. Inste public void doSomething(String userName, String userEmail, String userId) ``` -That makes it much easier to understand! Now we'll be able to read the code following the parameter with a much clearer understanding 🙂 +That makes it much easier to understand! Now we'll be able to read the code following the parameter with a much clearer understanding. 🙂 #### Pronounceable names @@ -312,14 +313,14 @@ Note that the arguments of a Fragment - `Fragment.getArguments()` - are also a B Example: ```java -// Note the value of the field is the same as the name to avoid duplication issues -static final String PREF_EMAIL = "PREF_EMAIL"; -static final String BUNDLE_AGE = "BUNDLE_AGE"; -static final String ARG_USER_ID = "ARG_USER_ID"; + // Note the value of the field is the same as the name to avoid duplication issues + static final String PREF_EMAIL = "PREF_EMAIL"; + static final String BUNDLE_AGE = "BUNDLE_AGE"; + static final String ARG_USER_ID = "ARG_USER_ID"; -// Intent-related items use full package name as value -static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME"; -static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER"; + // Intent-related items use full package name as value + static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME"; + static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER"; ``` @@ -333,9 +334,9 @@ Any declaration of variables should not use any special form of alignment, for e This is fine: ```java + private String username = "hitherejoe"; private int userId = 8; private int count = 0; - private String username = "hitherejoe"; ``` Avoid doing this: @@ -419,8 +420,8 @@ In the case that a method contains long parameters, we should line break where a ```java private void someMethod(Context context, String someLongStringName, String text, - long thisIsALong, String anotherString) { - } + long thisIsALong, String anotherString) { + } ``` And when calling that method we should break after the comma of each parameter: @@ -479,7 +480,7 @@ Not this: #### Inline comments -Where necessary, inline comments should be used to provide a meaningful description to the reader on what a specific piece of code does. They should only be used in situations where the code may be complex to understand. In most cases however, code should be written in a way that it easy to understand without comments 🙂 +Where necessary, inline comments should be used to provide a meaningful description to the reader on what a specific piece of code does. They should only be used in situations where the code may be complex to understand. In most cases however, code should be written in a way that it easy to understand without comments. 🙂 **Note:** Code comments do not have to, but should try to, stick to the 100 character rule. @@ -502,17 +503,17 @@ When creating class comments they should be meaningful and descriptive, using li ```java /** - * RecyclerView adapter to display a list of {@link Post}. - * Currently used with {@link PostRecycler} to show the list of Post items. - */ + * RecyclerView adapter to display a list of {@link Post}. + * Currently used with {@link PostRecycler} to show the list of Post items. + */ ``` Don’t leave author comments, these aren’t useful and provide no real meaningful information when multiple people are to be working on the class. ```java /** - * Created By Joe 18/06/2016 - */ + * Created By Joe 18/06/2016 + */ ``` ### TODO @@ -520,12 +521,12 @@ Don’t leave author comments, these aren’t useful and provide no real meaning Use TODO comments for code that is temporary, a short-term solution, or good-enough but not perfect. TODOs should include the string TODO in all caps, followed by a colon: ```java -// TODO: Remove this code after the UrlTable2 has been checked in. + // TODO: Remove this code after the UrlTable2 has been checked in. ``` and ```java -// TODO: Change this to use a flag instead of a constant. + // TODO: Change this to use a flag instead of a constant. ``` If your TODO is of the form "At a future date do something" make sure that you either include a very specific date ("Fix by November 2005") or a very specific event ("Remove this code after all production mixers understand protocol V7."). @@ -568,25 +569,27 @@ This makes sectioned methods easier to located in a class. Avoid not handling exceptions in the correct manner. For example: ```java - public void setUserId(String id) { - try { - mUserId = Integer.parseInt(id); - } catch (NumberFormatException e) { } - } + public void setUserId(String id) { + try { + mUserId = Integer.parseInt(id); + } catch (NumberFormatException e) { + // <- wrong! + } + } ``` This gives no information to both the developer and the user, making it harder to debug and could also leave the user confused if something goes wrong. When catching an exception, we should also always log the error to the console for debugging purposes and if necessary alert the user of the issue. For example: ```java - public void setCount(String count) { - try { - count = Integer.parseInt(id); - } catch (NumberFormatException e) { - count = 0; - Log.e(TAG, "There was an error parsing the count " + e); - DialogFactory.showErrorMessage(R.string.error_message_parsing_count); - } - } + public void setCount(String count) { + try { + count = Integer.parseInt(id); + } catch (NumberFormatException e) { + count = 0; + Log.e(TAG, "There was an error parsing the count " + e); + DialogFactory.showErrorMessage(R.string.error_message_parsing_count); + } + } ``` Here we handle the error appropriately by: @@ -600,30 +603,32 @@ Here we handle the error appropriately by: Catching exceptions generally should not be done: ```java - public void openCustomTab(Context context, Uri uri) { - Intent intent = buildIntent(context, uri); - try { - context.startActivity(intent); - } catch (Exception e) { - Log.e(TAG, "There was an error opening the custom tab " + e); - } - } + public void openCustomTab(Context context, Uri uri) { + Intent intent = buildIntent(context, uri); + try { + context.startActivity(intent); + } catch (Exception e) { + Log.e(TAG, "There was an error opening the custom tab " + e); + } + } ``` Why? -*Do not do this. In almost all cases it is inappropriate to catch generic Exception or Throwable (preferably not Throwable because it includes Error exceptions). It is very dangerous because it means that Exceptions you never expected (including RuntimeExceptions like ClassCastException) get caught in application-level error handling. It obscures the failure handling properties of your code, meaning if someone adds a new type of Exception in the code you're calling, the compiler won't help you realize you need to handle the error differently. In most cases you shouldn't be handling different types of exception the same way.* - taken from the Android Code Style Guidelines +Taken from the Android code style guide: + +Do not do this. In almost all cases it is inappropriate to catch generic Exception or Throwable (preferably not Throwable because it includes Error exceptions). It is very dangerous because it means that Exceptions you never expected (including RuntimeExceptions like ClassCastException) get caught in application-level error handling. It obscures the failure handling properties of your code, meaning if someone adds a new type of Exception in the code you're calling, the compiler won't help you realize you need to handle the error differently. In most cases you shouldn't be handling different types of exception the same way. Instead, catch the expected exception and handle it accordingly: ```java public void openCustomTab(Context context, Uri uri) { - Intent intent = buildIntent(context, uri); - try { - context.startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.e(TAG, "There was an error opening the custom tab " + e); - } + Intent intent = buildIntent(context, uri); + try { + context.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "There was an error opening the custom tab " + e); + } } ``` @@ -633,15 +638,15 @@ Where exceptions execute the same code, they should be grouped in-order to incre ```java public void openCustomTab(Context context, @Nullable Uri uri) { - Intent intent = buildIntent(context, uri); - try { - context.startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.e(TAG, "There was an error opening the custom tab " + e); - } catch (NullPointerException e) { - Log.e(TAG, "There was an error opening the custom tab " + e); - } catch (SomeOtherException e) { - // Show some dialog + Intent intent = buildIntent(context, uri); + try { + context.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "There was an error opening the custom tab " + e); + } catch (NullPointerException e) { + Log.e(TAG, "There was an error opening the custom tab " + e); + } catch (SomeOtherException e) { + // Show some dialog } } ``` @@ -650,13 +655,13 @@ You could do this: ```java public void openCustomTab(Context context, @Nullable Uri uri) { - Intent intent = buildIntent(context, uri); - try { - context.startActivity(intent); - } catch (ActivityNotFoundException e | NullPointerException e) { - Log.e(TAG, "There was an error opening the custom tab " + e); - } catch (SomeOtherException e) { - // Show some dialog + Intent intent = buildIntent(context, uri); + try { + context.startActivity(intent); + } catch (ActivityNotFoundException e | NullPointerException e) { + Log.e(TAG, "There was an error opening the custom tab " + e); + } catch (SomeOtherException e) { + // Show some dialog } } ``` @@ -681,7 +686,7 @@ When you want to use class Bar from package foo,there are two possible ways to i import foo.*; ``` -Potentially reduces the number of import statements. +Potentially reduces the number of import statements: ```java import foo.Bar; @@ -702,40 +707,40 @@ All unused fields, imports, methods and classes should be removed from the code Braces should always be used on the same line as the code before them. For example, avoid doing this: ```java - class SomeClass +class SomeClass +{ + private void someFunction() { - private void someFunction() - { - if (isSomething) - { + if (isSomething) + { - } - else if (!isSomethingElse) - { + } + else if (!isSomethingElse) + { - } - else - { + } + else + { - } - } + } } +} ``` And instead, do this: ```java - class SomeClass { - private void someFunction() { - if (isSomething) { +class SomeClass { + private void someFunction() { + if (isSomething) { - } else if (!isSomethingElse) { + } else if (!isSomethingElse) { - } else { + } else { - } - } + } } +} ``` Not only is the extra line for the space not really necessary, but it makes blocks easier to follow when reading the code. @@ -804,7 +809,7 @@ and takes up far fewer lines of code than this: #### Annotation practices -Taken from the Android code style guide: +Taken from the Android code style guide: **@Override:** The `@Override` annotation must be used whenever a method overrides the declaration or implementation from a super-class. For example, if you use the `@inheritdocs` Javadoc tag, and derive from a class (not an interface), you must also annotate that the method `@Overrides` the parent class's method. @@ -827,9 +832,6 @@ Annotations that are applied to a method or class should always be defined in th @Bind(R.id.layout_coordinator) CoordinatorLayout coordinatorLayout; - @Bind(R.id.layout_coordinator) - CoordinatorLayout coordinatorLayout; - @Inject MainPresenter mainPresenter; @@ -837,10 +839,10 @@ Annotations that are applied to a method or class should always be defined in th @AnotherAnnotation public class SomeClass { - @SomeAnotation - public String getMeAString() { + @SomeAnotation + public String getMeAString() { - } + } } ``` @@ -943,7 +945,9 @@ When creating new instances of a fragment or activity that involves passing data The scope of local variables should be kept to a minimum (Effective Java Item 29). By doing so, you increase the readability and maintainability of your code and reduce the likelihood of error. Each variable should be declared in the innermost block that encloses all uses of the variable. -Local variables should be declared at the point they are first used. Nearly every local variable declaration should contain an initializer. If you don't yet have enough information to initialize a variable sensibly, you should postpone the declaration until you do. - taken from the Android code style guidelines +Taken from the Android code style guide: + +Local variables should be declared at the point they are first used. Nearly every local variable declaration should contain an initializer. If you don't yet have enough information to initialize a variable sensibly, you should postpone the declaration until you do. ### Force non-instantiability @@ -954,7 +958,7 @@ class DateTimeUtils { /** * Prevents instantiation - **/ + */ private DateTimeUtils() {} static String formatDate(Date date) { diff --git a/Manifest.md b/Manifest.md index 11dc092..2ff30fa 100644 --- a/Manifest.md +++ b/Manifest.md @@ -2,9 +2,9 @@ ## Manifest File structure -The code snippet below shows the general structure of the manifest file and every element that it can contain.It is preferable to maintain the order of the elements. +The code snippet below shows the general structure of the manifest file and every element that it can contain. It is preferable to maintain the order of the elements. -``` +```xml diff --git a/ProjectStructure.md b/ProjectStructure.md index 7da1fdb..662c74f 100644 --- a/ProjectStructure.md +++ b/ProjectStructure.md @@ -18,33 +18,19 @@ To see the actual file structure of the project including all files hidden from When you select Project view, you can see a lot more files and directories. The most important of which are the following: module-name/ - build/ Contains build outputs. - libs/ Contains private libraries. - src/ Contains all code and resource files for the module in the following subdirectories: - androidTest/ Contains code for instrumentation tests that run on an Android device. For more information, see the Android Test documentation. - main/ Contains the "main" sourceset files: the Android code and resources shared by all build variants (files for other build variants reside in sibling directories, such as src/debug/ for the debug build type). - - AndroidManifest.xml Describes the nature of the application and each of its components. For more information, see the AndroidManifest.xmldocumentation. - - java/ Contains Java code sources. - - jni/ Contains native code using the Java Native Interface (JNI). For more information, see the Android NDK documentation. - + assets/ Contains files that should be compiled into an .apk file as-is. You can navigate this directory in the same way as a typical file system using URIs and read files as a stream of bytes using the AssetManager. For example, this is a good location for textures and game data. gen/ Contains the Java files generated by Android Studio, such as your R.java file and interfaces created from AIDL files. - + java/ Contains Java code sources. + jni/ Contains native code using the Java Native Interface (JNI). For more information, see the Android NDK documentation. res/ Contains application resources, such as drawable files, layout files, and UI string. See Application Resources for more information. - - assets/ Contains file that should be compiled into an .apk file as-is. You can navigate this directory in the same way as a typical file system using URIs and read files as a stream of bytes using the AssetManager. For example, this is a good location for textures and game data. - + AndroidManifest.xml Describes the nature of the application and each of its components. For more information, see the AndroidManifest.xml documentation. test/ Contains code for local tests that run on your host JVM. - build.gradle (module) This defines the module-specific build configurations. - build.gradle (project) This defines your build configuration that apply to all modules. This file is integral to the project, so you should maintain them in revision control with all other source code. -For information about other build files, see [Configure Your Build] (https://developer.android.com/studio/build/index.html). +For information about other build files, see [Configure Your Build](https://developer.android.com/studio/build/index.html). diff --git a/ResourcesGuidelines.md b/ResourcesGuidelines.md index a96a9ab..639fb61 100644 --- a/ResourcesGuidelines.md +++ b/ResourcesGuidelines.md @@ -78,16 +78,18 @@ All IDs should be prefixed using the name of the element that they have been dec | ImageView | imageview_ | | Button | button_ | | TextView | textview_ | -| EditText | edittext_ | +| EditText | edittext_ | | View | view_ | | ProgressBar | progressbar_ | For example: +```xml +``` Views that typically are only one per layout, such as a toolbar, can simply be given the id of it's view type. E.g.```toolbar```. @@ -103,6 +105,7 @@ Ordering attributes not only looks tidy but it helps to make it quicker when loo For example: +```xml