Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

Android Clean Code

No description
by

Felipe Costa

on 20 June 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Android Clean Code

Android Clean Code
Boilerplate code
Seção de código que é incluído em vários lugares com pouca ou nenhuma alteração. Muito verboso, o programador acaba escrevendo muito código a fim de fazer pouca coisa.
Annotation
Annotation é um tipo de metadado. Em Java, uma Annotation é uma forma sintática de metadado que pode ser adicionada ao código: Classes, métodos, variáveis, parametros e pacotes. As annotations podem: ser embutidas em arquivos .class gerados pelo compilador e mantidos pela JVM e então influenciar durante a execução; Informar ao compilador a respeito de algo; e Compile-time and deployment-time processing
Inverse of Control
Inversion of Control(IoC) significa que o fluxo de execução não é feito pelo programador, e sim pelo framework em questão. O framework chama o programador, ao invés do inverso.
Dependency Injection
Dependency Injection(DI) significa dar um objeto suas variáveis de instância.
RoboGuice
&
AndroidAnnotations

RoboGuice: um framework de DI para Android.

AndroidAnnotations é um framework cujo objetivo é reduzir código boilerplate com o uso de Annotations.
public class MyActivity extends Activity {
private TextView label;

private Drawable image;

private SearchManager searchManager;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myactivity);
this.label = (TextView) findViewById(R.id.mylabel);
this.image = getResources().getDrawable(R.drawable.myimage);
this.searchManager = (SearchManager) getSystemService(Activity.SEARCH_SERVICE);
}
}
Anotações Padrões
@Override
@Deprecated
@SuppressWarnings
Um exemplo do JPA/Hibernate:

@Entity
@Table(name = "usr") // @Table is optional, but "user" is a keyword in many SQL variants
public class User {
@Id // @Id indicates that this it a unique primary key
@GeneratedValue // @GeneratedValue indicates that value is automatically generated by the server
private Long id;

@Column(length = 32, unique = true)
// the optional @Column allows us makes sure that the name is limited to a suitable size and is unique
private String name;

// note that no setter for ID is provided, Hibernate will generate the ID for us

public long getId() {
return id;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}
public void testNewUser() {

EntityManager entityManager = Persistence.createEntityManagerFactory("tutorialPU").createEntityManager();

entityManager.getTransaction().begin();

User user = new User();

user.setName(Long.toString(new Date().getTime()));

entityManager.persist(user);

entityManager.getTransaction().commit();

// see that the ID of the user was set by Hibernate
System.out.println("user=" + user + ", user.id=" + user.getId());

User foundUser = entityManager.find(User.class, user.getId());

// note that foundUser is the same instance as user and is a concrete class (not a proxy)
System.out.println("foundUser=" + foundUser);

assertEquals(user.getName(), foundUser.getName());

entityManager.close();
}
JUnit4
public class JunitTest1 {

private Collection collection;

@BeforeClass
public static void oneTimeSetUp() {
// one-time initialization code
System.out.println("@BeforeClass - oneTimeSetUp");
}

@AfterClass
public static void oneTimeTearDown() {
// one-time cleanup code
System.out.println("@AfterClass - oneTimeTearDown");
}

@Before
public void setUp() {
collection = new ArrayList();
System.out.println("@Before - setUp");
}

@After
public void tearDown() {
collection.clear();
System.out.println("@After - tearDown");
}

@Test
public void testEmptyCollection() {
assertTrue(collection.isEmpty());
System.out.println("@Test - testEmptyCollection");
}

@Test
public void testOneItemCollection() {
collection.add("itemA");
assertEquals(1, collection.size());
System.out.println("@Test - testOneItemCollection");
}
}
Sem IoC:

puts 'What is your name?'
name = gets
process_name(name)
puts 'What is your quest?'
quest = gets
process_quest(quest)
Com IoC:

root = TkRoot.new()
name_label = TkLabel.new() { text "What is Your Name?" }
name_label.pack
name = TkEntry.new(root).pack
name.bind("FocusOut") { process_name(name) }
quest_label = TkLabel.new() { text "What is Your Quest?" }
quest_label.pack
quest = TkEntry.new(root).pack
quest.bind("FocusOut") { process_quest(quest) }
Tk.mainloop()
Sem DI:

public class Example {
private DatabaseThingie myDatabase;

public Example() {
myDatabase = new DatabaseThingie();
}

public void DoStuff() {
...
myDatabase.GetData();
...
}
}
Com DI:

public class Example {
private DatabaseThingie myDatabase;

public Example() {
myDatabase = new DatabaseThingie();
}

public Example(DatabaseThingie useThisDatabaseInstead) {
myDatabase = useThisDatabaseInstead;
}

public void DoStuff() {
...
myDatabase.GetData();
...
}
}
Exemplo de utilização:

public class ExampleTest {
TestDoStuff() {
MockDatabase mockDatabase = new MockDatabase();

// MockDatabase is a subclass of DatabaseThingie, so we can
// "inject" it here:
Example example = new Example(mockDatabase);

example.DoStuff();
mockDatabase.AssertGetDataWasCalled();
}
}
No Android, todo o padrão de Activites, definido no Manifest, e de Views através do setContentView e findById.

public class MyActivity extends Activity {

private TextView label;

private Drawable image;

private SearchManager searchManager;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myactivity);
this.label = (TextView) findViewById(R.id.mylabel);
this.image = getResources().getDrawable(R.drawable.myimage);
this.searchManager = (SearchManager) getSystemService(Activity.SEARCH_SERVICE);
}
}
Android:
public class MainApplication extends Application {

private MyService service;

@Override
public void onCreate() {
super.onCreate();
service = new MyServiceImpl();
}

public MyService getMyService() {
return this.service;
}
}

public class MainActivity extends Activity {

private MyService service;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainApplication app = (MainApplication) getApplication();
service = app.getMyService();
}
}
Uso de anotações
Utiliza o Guice(frameworkd de DI desenvolvido pelo Google)
Possibilidade de extensão
As injeções acontecem em runtime que pode impactar na perfomace
Aumento do tamanho da aplicação em 400kB
RoboGuice
AndroidAnnotations
Redução de código boilerplate
As injeções ocorrem em compile time, gerando uma subclasse.
Integração com RoboGuice
Aumento do tamanho da aplicação em 50kB
Utilização do Sprint Android
Rest Client: RestTemplate, Jasckon e Google Gson
Projeto
Exemplo de Annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test {
String info() default "";
}
class Annotated {
@Test(info = "AWESOME")
public void foo(String myParam) {
System.out.println("This is " + myParam);
}
}
class TestAnnotationParser {
public void parse(Class clazz) throws Exception {
Method[] methods = clazz.getMethods();


for (Method method : methods) {
if (method.isAnnotationPresent(Test.class)) {
Test test = method.getAnnotation(Test.class);
String info = test.info();

if ("AWESOME".equals(info)) {
System.out.println("info is awesome!");
// try to invoke the method with param
method.invoke(
Annotated.class.newInstance(),
info
);
}
}
}
}
public class Demo {
public static void main(String[] args) throws Exception {
TestAnnotationParser parser = new TestAnnotationParser();
parser.parse(Annotated.class);
}
}
Exemplo
@EActivity(R.layout.translate) // Sets content view to R.layout.translate
public class TranslateActivity extends Activity {

@ViewById // Injects R.id.textInput
EditText textInput;

@ViewById(R.id.myTextView) // Injects R.id.myTextView
TextView result;

@AnimationRes // Injects android.R.anim.fade_in
Animation fadeIn;

@Click // When R.id.doTranslate button is clicked
void doTranslate() {
translateInBackground(textInput.getText().toString());
}

@Background // Executed in a background thread
void translateInBackground(String textToTranslate) {
String translatedText = callGoogleTranslate(textToTranslate);
showResult(translatedText);
}

@UiThread // Executed in the ui thread
void showResult(String translatedText) {
result.setText(translatedText);
result.startAnimation(fadeIn);
}

// [...]
}
Full transcript