31 Jan 2020
|
TIL
Today I Leaned
Spinner
에 라디오 버튼을 구현하는 법을 찾아 한참 삽질했다. 결론은, 아래와 같이 하면 된다.
activity_main.xml (스피너를 넣을 화면에 스피너 생성)
<!--activity_main.xml-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Spinner
android:id="@+id/spinner"
android:layout_width="200dp"
android:layout_height="50dp"
android:spinnerMode="dialog"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
스피너에 넣을 값을 values
>strings.xml
에 저장(파일명은 상관없음)
<!--strings.xml-->
<resources>
<string-array name="stringArray">
<item>apple</item>
<item>banana</item>
<item>citrus</item>\
</string-array>
</resources>
메인 액티비티에서 어답터로 스피너를 생성하고, 값을 넣어준다. 나는 이 부분에서 삽질을 했다. spinner에 radio button을 나타나게 하는 방법을 갖가지 검색어로 구글링했을 때에는 adapter.setDropDownViewResource
에 android.R.layout.simple_spinner_dropdown_item
레이아웃을 사용하여 아이템을 보여주니 라디오버튼이 나왔었다. 하지만 이것은 옛날 자료였고 라이브러리가 변경된 것이다..ㅜ 지금은 아래와 같이 android.R.layout.simple_list_item_single_choice
혹은 android.R.layout.simple_list_item_single_choice
레이아웃을 적용해주면 스피너 아이템에 라디오버튼이 나타난다.
(검색 범위를 2015년부터로 바꾸고나서 바로 찾았다. 진작 했으면 시간을 절약했을것을.. 반성하자)
class MainActivity : AppCompatActivity(), AdapterView.OnItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ArrayAdapter.createFromResource(this, R.array.stringArray, android.R.layout.simple_spinner_item).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice)
spinner.adapter = adapter
spinner.onItemSelectedListener = this
}
}
}
20 Jan 2020
|
Java
객체지향 개발 5대 원리 SOLID
-
SRP(Single Responsibility Principle; 단일 책임 원칙)
: 한 클래스는 하나의 책임만을 가져야 한다. 모든 클래스의 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화(encapsulation)해야한다. 클래스가 제공하는 모든 기능은 이 책임 원칙에 부합해야 한다.
로버트 마틴은 ‘책임’을 ‘변경하려는 이유’ 로 정의하였다. 어떤 클래스나 모듈은 변경하려는 단 하나의 이유만을 가져야한다고 말한다. 한 클래스를 하나의 관심사에 집중하도록 유지하는 것이 중요한 이유는, 이것이 클래스를 더욱 튼튼하게 만들기 때문이다. 여러가지 관심사가 하나의 클래스에 있다면, 하나의 책임을 수정할 때 다른 코드가 망가질 위험이 높다.
-
OCP(Open-Closed Principle; 개방 폐쇄 원칙)
: 소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에는 열려(open)있으나 변경에는 닫혀(close)있어야 한다. 프로그래머는 추상화에 의존해야하며 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법 중 하나이다. 소프트웨어 개발 작업에 이용된 많은 모듈 중에 하나에 수정을 가할 때 그 모듈을 이용하는 다른 모듈을 모두 고쳐야 한다면, 이와 같은 프로그램은 수정하기 어렵다. 개발-폐쇄 원칙은 시스템의 구조를 올바르게 리팩토링하여 나중에 이와 같은 유형의 변경이 더 이상의 수정을 유발하지 않도록 하는 것이다.
아래는 개방-폐쇄 원칙의 두 가지 속성이다.
- 확장에 대해 열려 있다: 애플리케이션의 요구 사항이 변경될 때, 이 변경에 맞게 새로운 동작을 추가해 모듈을 확장할 수 있다.
- 수정에 대해 닫혀 있다: 모듈의 소스코드나 바이너리 코드를 수정하지 않아도 모듈의 기능을 확장하거나 변경할 수 있다. 그 모듈의 실행 가능한 바이너리 형태나 링크 가능한 라이브러리(ex. 자바의 .jar)를 건드릴 필요가 없다.
-
LSP(The LIskov Substitution Principle; 리스코브 치환 원칙)
: 프로그램의 객체는 프로그램의 정확성을 꺠뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. 치환성(substitutability)은 객체 지향 프로그래밍의 원칙이다. 컴퓨터 프로그램에서 자료형 S가 자료형 T의 하위형이라면 필요한 프로그램의 속성(정확성, 수행하는 업무 등)의 변경 없이 자료형 T의 객체를 자료형 S의 객체로 교체(치환)할 수 있어야 한다는 뜻이다. (이부분이 이해가 안간다. 자바에서 자동으로 다운캐스팅이 되는 것…?)
-
ISP(Interface Segregation Principle; 인터페이스 분리 원칙)
: 클라이언트는 자신이 이용하지 않는 메서드에 의존하지 않아야 한다. 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 하는 원칙이다. 이러한 작은 단위들을 역할 인터페이스 라고도 한다. 인터페이스 분리 원칙을 통해 시스템의 내부 의존성을 약화시켜 리팩토링, 수정, 재배포를 쉽게 할 수 있다.
-
DIP(Dependency Inversion Principle; 의존성 역전 원칙)
: 의존성 역전 원칙은 크게 두 가지 내용을 담고 있다.
- 첫째, 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
- 둘째, 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.
이러한 원칙은 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존 관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다.
정보 은닉과 캡슐화의 차이점?
이펙티브 자바 아이템 15(클래스와 멤버의 접근 권한을 최소화하라)를 보다가 정보 은닉과 캡슐화가 자꾸 혼동되었다. 구글에 ‘information hiding vs encapsulation’이라고 검색해보았다. 나같은 사람들을 위해 친절하게도 TechDifferences라는 웹사이트가 있었다. 아래는 이 웹사이트에 설명된 정보 은닉과 캡슐화의 차이점이다.
캡슐화란 클래스 내부에 멤버 데이터와 메서드의 구현을 감싸는 것을 의미한다. 클래스 안에 모든 데이터 멤버와 메서드의 구현이 캡슐화되어 있으면, 해당 클래스의 객체에서 수행하는 동작만 메서드의 이름으로 설명해주면 된다. 정보 은닉은 클래스의 멤버를 부적절하거나(illegal) 허가되지 않은 접근(unauthorized access)으로부터 보호하는 것을 의미한다.
정보 은닉과 캡슐화의 가장 큰 차이점은, 정보 은닉은 데이터의 보안에 중점을 두고 캡슐화는 시스템의 복잡성을 숨기는 데에 중점을 둔다는 것이다. 그 외의 차이점들은 아래의 표에 정리되어 있다.
비교 기준 |
정보 은닉 |
캡슐화 |
Basic |
정보 은닉은 데이터의 보안과 복잡성을 감추는 것이다. |
캡슐화는 시스템의 복잡성을 감추기 위해 데이터를 감싸는(wrap)것이다. |
Focus |
정보 은닉은 캡슐 내부 데이터를 사용하는 것을 금지/허용하는 것이 중점이다. |
캡슐화는 복잡한 데이터를 감싸는 것이 중점이다. |
Access Specifier |
정보 은닉에서 데이터는 항상 private이며 외부에서 접근할 수 없다. |
캡슐화에서 데이터는 private 혹은 public일수도 있다. |
Process |
정보 은닉은 프로세스이자 테크닉이다. |
캡슐화는 정보 은닉의 부차적인 과정이다. |
즉, (내가 이해한 바에 의하면..) 정보 은닉은 private 접근 제어자를 사용하여 클래스 외부에서 내부 데이터에 접근할 수 없도록 하는 것을 의미한다. 이펙티브 자바에 나온 정보은닉의 장점은 아래와 같다.
- 시스템 개발 속도를 높인다. 여러 컴포넌트를 병렬로 개발할 수 있기 때문이다.
- 시스템 관리 비용을 낮춘다. 각 컴포넌트를 더 빨리 파악하여 디버깅할 수 있고, 다른 컴포넌트로 교체하는 부담도 적기 때문이다.
- 정보 은닉 자체가 성능을 높여주지는 않지만, 성능 최적화에 도움을 준다. 완성된 시스템을 프로파일링해 최적화할 컴포넌트를 정한 다음, 다른 컴포넌트에 영향을 주지 않고 해당 컴포넌트만 최적화할 수 있기 때문이다.
- 소프트웨어 재사용성을 높인다. 외부에 거의 의존하지 않고 독자적으로 동작할 수 있는 컴포넌트라면 그 컴포넌트와 함께 개발되지 않은 낯선 환경에서도 유용하게 쓰일 가능성이 크기 때문이다.
- 큰 시스템을 제작하는 난이도를 낮춰준다. 시스템 전체가 아직 완성되지 않은 상태에서도 개별 컴포넌트의 동작을 검증할 수 있기 때문이다.
참고 자료