Dog Class -> 품종, 색깔, 나이 attributes 혹은 먹다, 짖다, 꼬다 등의 행위 수행 가능.
ex2) Person Class
A Person class can have specific information such as name, age, and address
class Person {
String name;
int age;
void introduce() {
System.out.println("안녕하세요, 제 이름은 " + name + "이고, "
+ age + "살 입니다.");
}
}
// 클래스에서 객체 생성
Person person = new Person();
person.name = "John Doe";
person.age = 30;
person.introduce();
This code defined a 'Person' class.
It contains name and age variables and an include method.
The introduce method prints personal information. And create an object from the class, and set its variables to specific values. Finally, we call the object's introduce method to display the information.
프로젝트 진행중 필수적으로 나타나는 오류와 버그에 대해 전반적인 과정을 문서화를 통해 예방.
문제해결 과정을 기록,상기 -> 추후 같은 문제 발생 시 신속 대처
트러블슈팅 절차를 통해 계속되는 추가 질문을 답변하고 해결책 목록을 좁혀나가는 단계를 밟아나가거나 문제 해결에 도움이 될 해결책을 즉시 구현.
⛔트러블 슈팅의 기본적인 개념
가장 단순하고 빈도 높은 원인에서 가능성을 지워가는 것
이게 핵심이다.트러블 슈팅은 제거법의 개념을 기본으로 하고있다.pc가 멈췄어요 와 같은 트러블에 대해서는 전원의 on/off 여부, 전원플러그는 콘센트에 꽂혀있는가 와 같은 인과관계에서 하나씩 가능성을 제거해나간다.
⛔트러블 슈팅 방법
1. 문제 정의
문제가 되는 동작 혹은 원인 확인ex) 배탈나버림
2. 사실 수집
해당 문제에 대한 정보 수집
문제를 재현하는 방법 수집ex) 배탈나게 한 음식에 대한 정보 수집
3. 원인추론
확인된 사실을 통해 원인 추론ex) 아 고기때문에 배탈난거같다 많이먹었거든
4. 조사방법 결정
증상과 추론 원인을 기반으로 어떤 순서로 문제를 해결할지 결정
보통 가능성이 높은 원인을 우선적으로 조사ex) 고기를 얼마나 먹었는지 엄마한테 물어보기로 결정
5. 조사 방법 구현
앞서 결정한 내용을 토대로 문제를 조사ex) 엄마 나 얼마나 먹었어? 한 5인분?
6. 결과 관찰
조사 방법을 구현하고 그 결과를 기록
만약 문제가 해결되지 않았다면 4번으로 돌아감ex) 아 5인분먹으면 배탈나는구나 이제 5인분말고 4인분까지 먹어야겟다
7. 문서 작성
문제를 해결한 순서를 정리해 문서화함ex) 머리에 새겨넣는다
⛔적절한 트러블 슈팅을 실현하기 위해서
예시를 쉽게 들어서 잘 대처할 수 있다고 생각이 들 수도 있지만 실제 운용 측면에서 트러블 슈팅에는 몇 가지 과제가 있어 생각처럼 운용이 되지 않는 경우도 있다.
우선순위에 따라 어떤 대응을 해야하나
개발운영팀에서 우선순위가 매우낮은 트러블이라도 문제가 발생하면 바로 대처해야된다. 우선순위가 매우 낮더라도 무시하지말고 우선도가 낮은 트러블에 대해 대처방안을 수립해야된다.대처 프로세스 체계화
이슈가 생겼을때 해당 이슈를 한명만 처리할 수밖에 없다면 그 한명은 업무쏠림으로 다른 업무에 무리가 갈 수가 있다. 또는 인원부족으로 신입이나 경력이 짧은 직원이 대처해야된다면 이를 어찌 해결해야될까?
이러한 상황을 피하기 위해 트러블 대응 업무를 체계화하고 매뉴얼로 문서화를 하여 표준화 하는 것이 중요하다. 그렇게 하면 누구라도 동일한 대응이 가능하여 원활하게 해결, 복구가 가능하다
⛔정리
개인적으로 개발이라는 분야는 트러블 슈팅을 통해 실력이 급상승할 수 있다는 생각을 가지고 있다. 처음 시작할때와 프로젝트를 시작하면서 겪었던 모든 오류와 과정을 몸소 겪으며 얻은 경험과 소스와 문서를 추후 다른 프로젝트를 진행하면서 생기는 오류에 대입해볼 수도 아니면 같은 오류일때 바로바로 대처가 가능하기 때문이다.
파이썬 머신러닝 프로젝트를 진행하면서 환경세팅에만 2주가 걸렸다. 난생 처음해보는 분야이기에 분명 구글에 검색한대로 따라하고 환경변수 설정하고 install하라는 모든 행동을 다했지만 안되어서 멘탈이 박살나기 직전까지 하다가 결국 해결했는데 이는 절대 잊어버릴 수가 없다.
면접에서 트러블슈팅 사례를 말해달라고 하면 당황하지말고 평소 개인 토이프로젝트나 프로젝트에 대한 트러블 슈팅에 대해 잘 숙지하고 정리를 해서 점수를 얻도록 하자.
class Product(val name: String, val price: Int)
interface Wheel {
fun roll()
}
//Kotlin에서는 인터페이스도 상위 인터페이스를 가질 수 있다.
interface Cart : Wheel {
//kotlin에서는 인터페이스의 Property도 존재 가능하다.
var coin: Int //MyCart Class에서 무조건 구현해야 하는 추상 프로퍼티다.
val weight : String
get() = "20KG"
fun add(product: Product)
fun rent() {
if (coin > 0) {
println("카트를 대여합니다.")
}
}
override fun roll() {
println("카트가 굴러갑니다.")
}
}
interface Order {
fun add(Product : product) {
println("${product.name} 주문이 완료 되었습니다.")
}
}
//Kotlin에서는 하나 이상의 인터페이스를 구현 할 수 있다.
class MyCart(override var coin: Int) : Cart, Order {
//Cart 인터페이스에서 구현해야하는 추상함수이기 때문에 오버라이드를 통해서 함수 생성
override fun add(product: Product){
if (coin <= 0) println("코인을 넣어주세요.")
else println("${product.name}이(가) 카트에 추가됐습니다.")
}
//복수개의 인터페이스에서 함수를 호출 할려고 하면 super<>키워드로 접근 가능하다.
super.add(product) //장난감 주문이 완료 되었습니다.
}
fun main() {
val cart = MyCart(coin = 100)
cart.rent() //카트를 대여합니다.
cart.roll() //카트가 굴러갑니다.
cart.add(Product(name="장난감",price = 1000)) //장난감이(가) 카트에 추가됐습니다.
}
특징:
①. Kotlin에서는 인터페이스에서도 상위 인터페이스를 가질 수 있다.
②. Kotlin에서는 Interface의 Property도 존재 가능 하다. "var coin: Int"
MyCart Class에서 무조건 구현해야 하는 추상 프로퍼티다. class MyCart(override var coin: Int) ③. 복수개의 인터페이스에서 함수를 호출하려고 하면 super <> 키워드로 접근 가능하다.
객체지향 핵심 원칙 중 하나인 상속은 상속을 통해 기존 코드를 재사용하거나 확장할 수 있다.
자바는 기본적으로 모든 클래스가 상속이 가능하나 상속에 따른 부작용이 발생할 경우를 대비해 final 키워드로 막을 수 있다.
대표적으로 System 클래스
자바의 모든 클래스의 조상은 Object인데, 코틀린의 모든 클래스의 조상은 "Any"이다.
Any는 equals,hashCode,toString 함수를 제공한다.
코틀린에서 작성하는 어떤 클래스든지 다 이런 함수들을 상속 받는다.
또한 코틀린의 클래스는 자바와 다르게 기본적으로 final class이다. final이기에 기본적으로 상속을 막고, 필요한 경우 open이라는 키워드를 통해 상속을 허용 가능하다.
open class Dog {
open var age: Int = 0
open fun bark() {
println("멍멍")
}
}
// : 뒤에 상위 클래스를 선언 하면 상속 코드 작성 가능하다.
open class Bulldog(overrid var age : Int = 0) : Dog() {
//하위클래스에서 상위클래스 age,bark 메서드를 재정의 하려면
overrid fun bark() { //overrid된 프로퍼티나,함수는 자동으로 open이 된다.
//println("컹컹")
super.bark() //상위 클래스의 함수나 프로퍼티들을 그대로 재사용할 수 있다.
}
}
abstract class Developer {
abstract var age: Int
abstract fun code(language: String)
}
//Developer 추상클래스를 상속받은 BackendDeveloper를 만들었다.
//이때, 하위클래스에서 구현해야하는 프로퍼티나 함수또한 abstarc함수를 사용하면 된다.
class BackendDeveloper(override var age : Int = 0) : Developer() {
override fun code(language: String) {
println("I code with $language")
}
}
fun main() {
val backendDeveloper = BackendDeveloper(age = 20)
println(backendDeveloper.age)//20
backendDeveloper.code("Kotlin")//I code with Kotlin
//val dog = Bulldog(age = 2)
//println(dog.age)//2
//dog.bark()//멍멍
}
class ChildBulldog : Bulldog () {
overrid var age: Int = 0
overrid fun bark() {
super.bark()
}
}
런타임은 프로그램의 수명 주기 중 실제로 코드가 실행 되면서, 메모리가 할당되고, 사용자와 상호 작용하며, 다양한 작업을 수행하는 시간이다. 런타임 오류는 이러한 실행 과정에서 발생하는 오류로, 일반적으로 프로그램의 논리적 오류, 잘못된 데이터 처리, 또는 예상하지 못한 상황에 대한 처리의 부재와 같은 문제로 인해 발생한다.
//클래스의 생성자를 만들 때, constructor keyword 사용 가능.
//constructor 생략 가능, 굳이 constructor를 쓰는 경우는, 특정 Annotation을 같이 쓰는 경우.
class Coffee //constructor
(
val name:String = "",
val price: Int = "0",
val iced : Booelan = false,
) {
val brand: String
//custom getter get() = "스타벅스" //String 표현식
get() {
return "스타벅스"
}
//var로 선언된 프로퍼티는 custom setter도 만들 수 있다.
var quantity : Int = 0
set(value) {
if (value > 0) { //수량이 0 이상인 경우에만 할당
field = value //field는 식별자. setter getter에 사용하게 되면 quantity 같은 이름이 접근한다.
}
}
}
class EmptyClass
fun main() {
val coffee = Coffee()
coffee.name = "아이스 아메리카노"
coffee.price = 2000
coffee.quantity = 1
coffee.iced = true
if(coffee.iced) {
println("아이스 커피")
} //아이스커피
println("${coffee.brand} ${coffe.name} 가격은 ${coffee.price} 수량은 ${coffee.quantity}")
//스타벅스 아이스 아메리카노 가격은 2000 수량은 1
}
fun main() {
try {
throw Exception()
}catch(e: Exception) {
println("에러 발생!") //에러 발생!
}
finally{
println("finally 실행!") //finally 실행!
}
//kotlin은 표현식 형태로서 try catch문이 가능하다.
val a = try {
"1234".toInt()
} catch (e: Exception) {
println("예외 발생 !")
}
println(a) //1234
//직접 Exception을 할려면 throw를 사용할 수 있다.
//throw Exception("예외 발생") //run창에 빨간 text로 : 예외 발생! 출력
val b : String? = null
val c = b ?: failFast("a is null")
println(c?.length)
//Noting에서 발생하면 아래 코드는 실행되지 않는다.
println("이 메세지는 출력 안됨 ")
}
fun failFast(message: String): Nothing {
throw IllegalArgumentException(message) //throw를 리턴하게 되면 Nothing 타입을 반환
}
자바를 포함한 많은 프로그래밍 언어에서 가장 많이 발생하는 유형이NullPointException 줄여서 NPE라고도 부른다.
자바에선 NPE를 줄이기위해 Optional을 지원 하기 시작했다.
자바의 Optional은 값을 래핑하기 때문에 객체 생성에 따른 호버헤드가 발생하고, 컴파일 단계에서 null 가능성을 검사하지 않는다.
코틀린을 비롯한 최신 언어에선 null 가능성을 컴파일러가 미리 감지해서 NPE 가능성을 줄일 수있다.
fun main() {
//컴파일 오류 val a : String = null
// var b : String = "aabbcc"
// b = null 컴파일 오류
var a : String? = null
println(a?.length) //null
var b: Int = if (a != null) a.length else 0
println(b) // null
//엘비스 연산자
//좌변이 null인 경우, 우변 값 반환
val c = a?.length ?: 0
println(c)
}
fun getNullStr(): String? = null
fun getLongthIfNotNull(str: String?) = str?.length ?:0
fun main() {
val nullableStr = getNullStr()
val nullableStrLength = nullableStr?.length ?: "문자길이".length
println(nullableStrLength) //4 (문자길이 반환해줌)
val length = getLengthIfNotNull(null)
println(length) //0 3line에 null이 아닌 경우 0을 출력하도록 되어있기에 0 출력
//throw NullPorinterException() //에러발생
val c: String? = null
val b = c!!.length //!!쓰게 되면,개발자가 봤을 때 이 코드는 널이 발생하지 않는 안전한 코드다.라고 컴파일러에게 알려줌
//Null을 없애주는 것은 아니고 널이 발생하든 안하든 개발자가 체크해야하는 부분이다.
}