- Understanding Clean Code in Android
- Before you start writing your code, it’s better that you understand how to manage your code and how to make your code scalable.
- What is “Clean Code”?
- — Must I care about it?
- Characteristics of a Clean code
- Create Meaningful Names
- — Class Names
- — Method Names
- — Use Problem Domain Names
- Writing your code using S.O.L.I.D Principles
- Single Responsibility Principle — SRP
- Open-Closed Principle — OCP
- Liskov Substitutions Principle — LSP
- Interface Segregation Principle — ISP
- Dependency Inversion Principle — DIP
- Conclusion
- Распознавание Barcode Android
- Создание нового проекта
- Интегрируем ZXing
- Сканируем
- Обработка результатов сканирования
- Разбираемся с Clean Code в Android
- Что такое «Чистый Код»?
- Я должен заботиться об этом?
- Признаки Чистого кода
- Пишите осознанные имена
- Имена классов
- Имена методов
- Пишите код, придерживаясь SOLID принципов
- Принцип единственную ответственности (S)
- Принцип открытости/закрытости (О)
- Принцип подстановки Барбары Лисков (L)
- Принцип разделения интерфейса
- Принцип инверсии зависимостей
Understanding Clean Code in Android
Before you start writing your code, it’s better that you understand how to manage your code and how to make your code scalable.
As Uncle Bob said in his book,
You are reading this “article” for two reasons. First, you are a programmer. Second, you want to be a better programmer. — Robert C. Martin
Like what he said, imagine that you are in a library, and you are looking for some books. If the library sorted and categorized their books, you will find your books faster. In addition, the cool interior design & architecture will make you feel comfortable inside the library while you are searching for your books.
Just like writing books, if you want to build something great, you have to know how to write and organize your code neatly. If you have team members or someone else that has your (legacy) code, they just need to see the variable names or packages or classes and they will understand right away. They don’t need to say “F**k” this code and start it again from zero.
What is “Clean Code”?
As you can see, it is not good enough if you finish your development faster if others cannot understand your code, because it will become another tech debt.
Your code has a definition of “Clean” if it can be understood easily by everyone on the team. Clean code can be read and enhanced by a developer other than its original author. With understandability comes readability, changeability, extensibility, and maintainability.
— Must I care about it?
The reason why you must care about your code is that your code will describe your thought process to others. That is why you have to start thinking about making your code more elegant, simple and readable.
Characteristics of a Clean code
- Your code should be elegant: Your code should make you smile the way a well-crafted music box or well-designed car would.
- Your code has been taken care of: Someone has taken the time to keep it simple and orderly. They have paid appropriate attention to details. They have cared.
- Your code has to be focused: Each function, each class, each module exposes a single-minded attitude that remains entirely undistracted, and unpolluted, by the surrounding details.
- Contains no duplication
- Runs all the tests
- Minimize the number of entities such as classes, methods, functions, and the like.
One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand. — Robert C. Martin
Create Meaningful Names
Choosing good names takes time but saves more than it takes. The name of a variable, function, or class, should answer all the big questions. It should tell you why it exists, what it does, and how it is used. If a name requires a comment, then the name doesn’t reveal its intent.
Let’s take a sample:
— Class Names
Classes and objects should have noun or noun phrase names like Customer, WikiPage, Account, and AddressParser. Avoid words like Manager, Processor, Data, or Info in the name of a class. A class name should not be a verb.
— Method Names
Methods should have verb or verb phrase names like postPayment, deletePage, or save. Accessors, mutators, and predicates should be named for their value and prefixed with get, set, and is according to the javabean standard.
— Use Problem Domain Names
When there is no “ programmer-eese” for what you’re doing, use the name from the problem domain. At least the programmer who maintains your code can ask a domain expert what it means.
Before we continue, take a break and make some coffee or grab some snacks. 😀
OK, now we continue about the writing your code using S.O.L.I.D principles.
Writing your code using S.O.L.I.D Principles
This principles are invented by Robert C. Martin (Uncle Bob), SOLID is a term describing a collection of design principles for good code.
Single Responsibility Principle — SRP
It means every class should have a single responsibility. There should never be more than one reason for a class to change. Just because you can add everything you want into your class doesn’t mean that you should. Split big classes into smaller ones, and avoid God Classes.
Lets take a sample:
We have an RecyclerView.Adapter with business logic inside onBindViewHolder.
It makes RecyclerView.Adapter not having a Single Responsibility because it has a business logic inside onBindViewHolder. This method is only responsible for setting up data into its view binding implementation.
Open-Closed Principle — OCP
Software entities should be open for extension but closed for modification. What it means is that if you write a Class A, and then your teammates want to make a modification in a function inside Class A, They can easily do that by extending Class A, instead of making a modification inside Class A.
The easy example would be the RecyclerView.Adapter class. You can easily extend this class and create your own custom adapter with custom behavior without modifying the existing RecyclerView.Adapter class.
Liskov Substitutions Principle — LSP
Child classes should never break the parent class’ type definitions.
It means that a subclass should override the methods from a parent class that does not break the functionality of the parent class. For example, you create an interface class that has an onClick() listener, and then you apply the listener in MyActivity and give it a toast action when the onClick() is called.
Interface Segregation Principle — ISP
The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.
It means that if you want to make a Class A and implement it in another class ( (Class B), it should not override all Class A methods inside class B. To make it clear and easy to understand,
Let’s take a sample: inside your activity, you need to implement SearchView.OnQueryTextListener() and only need the onQuerySubmit() method.
How to achieve that? simple, you just create a callback and a class that extends to SearchView.OnQueryTextListener().
And here is how to implement in view:
Or, if you are using Kotlin, you can use the Extension Function:
And last, here is how to implement in view:
Dependency Inversion Principle — DIP
Depend on Abstractions. Do not depend on concretions.
Uncle Bob’s definition of the Dependency Inversion Principle consists of two points:
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
High-level modules, which provide complex logic, should be easily reusable and unaffected by changes in low-level modules, which provide utility features. To achieve that, you need to introduce an abstraction that decouples the high-level and low-level modules from each other.
The easy example is in MVP pattern, you have an object of interfaces that help us to communicate with concrete classes. What it means is, UI classes (Activity/Fragment) don’t need to know the actual implementation of methods in Presenter. So, if you have any changes inside presenter, UI classes don’t need to know or care about the changes.
Let’s see it in this code example:
Now let’s see it in UserActivity:
So what we do is we create an interface which abstracts the implementation of a presenter and our view class keeps the reference of the PresenterInterface.
Conclusion
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. From now, you have to start thinking about what to implement and about future perspective that will be easy to update.
I know that if you have created an app before with nonsense naming, God classes, Spaghetti code, trust me, I have done the same thing. That’s why I share my knowledge about the Clean Code from Uncle Bob to you, and it is also be a reminder for me and I hope I can help you to understand it.
Last but not least, Comments/Suggestions are welcome as always. Keep learning and keep sharing.
Источник
Распознавание Barcode Android
В данной статье мы будем использовать ZXing (Zebra Crossing), чтобы расшифровать штрихкод в нашем Android приложении.
Используя ZXing, нам не нужно думать о том, что у пользователя нет сканера barcode, так как классы, предоставляемые библиотекой позаботятся об этом. Интегрируя ZXing в наше приложение мы можем предоставить пользователю более простую возможность сканировать шрихкоды, также это позволит нам сфокусироваться на разработке основной части приложения.
Создание нового проекта
Шаг 1
В Eclipse создайте новый Android проект. Введите имя приложения, проекта и название пакета.
Шаг 2
Откройте основной шаблон. Eclipse должен был создать стандартный шаблон. Внутри него замените существующий контент на кнопку
После кнопки добавим два текстовых поля, которые будут отображать результаты отсканированной информации.
Добавьте к кнопке текст. Откройте файл res/values/strings
Чтобы просканировать пользователь должен будет нажать на кнопку. Когда приложение получает результат распознавания, оно отобразит его в текстовых полях.
Интегрируем ZXing
Шаг 1
ZXing — библиотека с открытым исходным кодом, предоставляющая возможность распознавания штрихкодов на Android. Некоторые пользователи уже имеют установленное приложение ZXing, поэтому достаточно передать ему код и дождаться результатов. В данном приложении мы рассмотрим способ, вызывающий соответствующую функцию другого приложения. Если данное приложение отсутствует у пользователя, то будет выведено предложение скачать его.
В Eclipse добавим новый пакет в Ваш проект. Для этого кликнем правой кнопкой мыши по папке src и выберем «New»->«Package», а затем введем com.google.zxing.integration.android в качестве имени пакета.
Шаг 2
Eclipse предлагает несколько способов импортирования существующего кода в проект. В данной статье самым простым методом будет создание двух классов, содержащий код из ZXing. Кликните правой кнопкой мыши по Вашему проекту, выберете «New»->«Class» и введите «IntentIntegrator» в качестве названия класса. Остальные параметры Вы можете не изменять. Как только Вы создали класс, проделайте тоже самое, но назовите класс «IntentResult».
Скопируйте код из обоих классов библиотеки, а затем вставьте его в созданные классы.
Теперь Вы можете подключить файлы в основной класс
Вернемся на минутку и также подключим следующие файлы. Обратите внимание, что Eclipse мог уже их подключить за Вас
Изучите содержание двух классов. Изучив их Вы обнаружите, что они не считывают код. Эти два класса являются просто интерфейсами, предоставляющими доступ к функционалу сканирования.
Сканируем
Шаг 1
Давайте реализуем сканирование, когда пользователь нажимает на нашу кнопку. В главном файле приложения существует метод onCreate, который должен выглядеть примерно так
Перед данной функцией создайте следующие переменные, которые будут хранить нашу кнопку и два текстовых поля, созданных в шаблоне
После существующего кода в onCreate добавьте строки, которые будут инициализировать переменные
Теперь, добавим обработчик нажатия
Расширим класс, чтобы объявить интерфейс OnClickListener
Шаг 2
Теперь, мы можем реагировать на нажатие кнопки началом процесса сканирования. Добавим метод onClick
Проверяем, была ли нажата именно кнопка сканирования
Внутри блока с условием создадим экземпляр класса IntentIntegrator, который мы импортировали
Сейчас, давайте вызовем процедуру, которая начнет сканирование
В данный момент должно начаться распознавание, но только, если у пользователя установлено необходимое приложение. Если его нет, то будет предложено начать загрузку. Результат сканирования будет возвращен приложению.
Обработка результатов сканирования
Шаг 1
Сканер будет запущен, когда нажата кнопка. Затем будет возвращен результат сканирования в метод onActivityResult. Добавим его в наш код
Внутри функции постараемся обработать результат
Шаг 2
Как и любые другие данные, полученные от другого приложения, было бы не плохо проверить, что результат не пуст. Продолжим мы только, если у нас есть правильный результат
Если мы не получили результат сканирования (например, пользователь отменил сканирование), то мы просто выведем сообщение
Вернемся в блок с условием, давайте разберемся с тем, что нам вернула библиотека. Объект Intent Result имеет метод, обеспечивающий получение результата сканирования. Получим результат сканирования, как строку
Также, получим вид barcode
Шаг 3
Теперь, наше приложение имеет всю необходимую для отображения информацию. В нашей статье мы просто отобразим ее пользователю.
Запустите наше приложение на реальном устройстве вместо эмулятора, чтобы увидеть, как работает функционал распознавания штрихкодов. Попробуйте просканировать штрихкод с какой-нибудь книги или любого другого товара.
Результаты сканирования
Источник
Разбираемся с Clean Code в Android
Вы читаете эту статью по двум причинам. Первая — Вы программист, вторая — Вы хотите быть лучшим программистом.
Представьте, что Вы находитесь в библиотеке и ищете какие-то книги. Если библиотека сортирована, имеет категории книг, то вы быстро отыщите нужную Вам. Кроме того, крутой дизайн интерьера и архитектура сделает пребывание в этой библиотеке довольно комфортным для Вас.
Как и при написании книг, если вы хотите создать что-то великое, то вы должны знать как писать и как организовывать свой код. Если у вас есть члены команды или кто-то еще, у кого есть Ваш (устаревший) код, им просто нужно увидеть имена переменных или пакеты или классы, и они сразу поймут. Им не нужно говорить «Е**л» я этот код и начинать его снова с нуля.
Что такое «Чистый Код»?
Когда я писал этот код, только Бог и я знал как он работает!
Теперь только Бог знает это!
Перед тем как ты попытаешься оптимизировать эту рутину и это не приведет к успеху (наиболее вероятно), пожалуйста увеличь счетчик затраченного времени для предостережения следующего разработчика
Всего потрачено часов: 567
Как Вы можете видеть, недостаточно закончить разработку быстрее. Если в будущем в этом коде не смогут разобраться, то это так же станет техническим долгом.
Ваш код имеет состояние «Чистый», если его может понять каждый член Вашей команды. Чистый код может быть прочитан и улучшен любым разработчиком, отличным от первоначального автора. С пониманием приходит читаемость, изменяемость, расширяемость и ремонтопригодность.
Я должен заботиться об этом?
Причина, по которой Вы должны заботиться о чистоте своего кода, заключается в том, что Вы описываете ход своих мыслей другим разработчикам. Именно поэтому Вы должны заботиться о том, что Ваш код был более элегантным, простым и читаемым.
Признаки Чистого кода
Отличие между хорошим программистом и профессионалом в том, что профессиональный программист понимает, что понятность кода первостепенна. Профессионал использует эту силу для написания кода, который понятен всем — Robert C. Martin
Пишите осознанные имена
Выбор хорошего имени, может занять много времени, но в последствии оно сэкономит больше. Имя переменной, функции, класса должно отвечать на все значимые вопросы. Оно должно рассказать Вам, почему оно существует, зачем оно нужно и как его использовать. Если имя требует комментария, то имя не раскрывает своего предназначения
Имена классов
Классы и объекты должны быть существительными, например Сustomer, WikiPage, Account, and AddressParser. Избегайте таких слов как Manager, Processor, Data, или Info. Помните так же, что имя класса не должно быть глаголом.
Имена методов
Имена методов же должны быть глаголами, например postPayment, deletePage или save. Модификаторы доступа, предикаты должны быть названы по их значению и с префиксом get, set и согласно стандарту JavaBean.
Перед тем, как мы продолжим сделайте небольшой перерыв, запаситесь кофе и печеньками
Окей, теперь перейдем к SOLID принципам
Пишите код, придерживаясь SOLID принципов
Эти принципы были разработаны дядюшкой Бобом, SOLID это аббревиатура, описывающая набор принципов, предназначенных для написания хорошего кода.
Принцип единственную ответственности (S)
Это означает, что каждый класс должен нести только одну ответственность. Никогда не должно быть более одной причины для изменения класса. Не надо добавлять все в свой класс, просто потому что Вы можете это сделать. Разбивайте большие классы на более маленькие и избегайте God Classes.
У нас есть RecyclerView.Adapter с бизнес логикой внутри onBindViewHolder
Это делает RecyclerView.Adapter не имеющим единственную ответственность, потому что он содержит бизнес логику внутри onBindViewHolder. Этот метод отвечает только за вставку данных во view.
Принцип открытости/закрытости (О)
Программные сущности должны быть открыты для расширения, но закрыты для модификации. Это означает, что если Вы разрабатываете класс А и ваши коллеги захотят изменить функцию внутри этого класса. Они смогут легко это сделать, расширив этот класс без изменения самого класса.
Простой пример класс RecyclerView.Adapter. Вы можете с легкостью расширить его и создать свой собственный адаптер с нестандартным поведением без модификации самого RecyclerView.Adapter.
Принцип подстановки Барбары Лисков (L)
Дочерний класс должен дополнять родительский, а не изменять его. Это означает, что подкласс должен переопределять методы родительского, которые не нарушают функциональность этого родительского класса. Например мы создаем интерфейс класса, который имеет onClick() слушатель а затем вы применяете слушатель в MyActivity и даете ему действие Toast, когда вызывается onClick ().
Принцип разделения интерфейса
Этот принцип гласит, что клиент не должен быть зависим от методов, которые он не использует.
Это означает, что если Вы хотите написать класс А и добавить в него функциональность другого класса В. Нет необходимости переопределять все классы А внутри класса В.
Пример: в нашей активити, нам нужно реализовать SearchView.OnQueryTextListener(), но нам нужен только onQuerySubmit() метод.
Как мы это сделаем? Легко! Просто создадим callback и класс, расширяющий SearchView.OnQueryTextListener()
И вот так мы добавим это к нашей view
Или так, используя Extension Function в Kotlin
Принцип инверсии зависимостей
Зависимость на абстракциях, без зависимости на что-то конкретное.
Определение инверсии зависимостей от дядюшки Боба состоит из двух понятий.
Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба должны быть завязаны на абстракциях. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. Модули высоких уровней, которые реализуют комплексную логику, должны быть легко переиспользуемы без изменений в модулях нижнего уровня. Для этого Вам нужно ввести абстракцию, которая отделяет модули верхнего и нижнего уровней друг от друга.
Простой пример этого MVP паттерн. У Вас есть объект интерфейсов, который помогает Вам общаться с конкретными классами. Что имеется ввиду — классам UI (Activity/Fragment) не нужно знать фактическую реализацию методов презентера. Таким образом, если Вы делаете изменения внутри презентера, UI классы не должны волновать эти изменения
Давайте взглянем на пример
А теперь на активити
Таким образом мы создаем интерфейс, который абстрагирует реализацию презентатора, и наш класс view сохраняет ссылку на PresenterInterface.
Источник