├── .DS_Store ├── .github └── workflows │ └── main.yml ├── .gitignore ├── 10일 만에 끝내는 MBA ├── 1일차_마케팅.md ├── 2일차_윤리학.md ├── 4일차_조직행동론.md └── README.md ├── Clean Code ├── .gitignore ├── .idea │ ├── .gitignore │ ├── Clean Code.iml │ ├── aws.xml │ ├── codeStyles │ │ ├── Project.xml │ │ └── codeStyleConfig.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── 01_What_Clean_code_is.md ├── 02_Meaningful_name.md ├── 03_Method.md ├── 10장-클래스.md ├── 11장-시스템.md ├── 12장-창발성.md ├── 1장-깨끗한코드.md ├── 2장-의미 있는 이름.md ├── 3장-함수.md ├── 5장-형식-맞추기.md ├── 6장-객체와-자료-구조.md ├── 7장-오류처리.md ├── 8장-경계.md ├── 9장-단위테스트.md └── README.md ├── Cracking the coding interview ├── READMD.md ├── [자료구조]배열과문자열.md └── [자료구조]연결리스트.md ├── DDD start ├── 01-도메인 모델.md ├── 02-아키텍쳐-개요.md ├── 03-애그리거트.md ├── 06-응용서비스와-표현영역.md ├── 07-도메인서비스.md ├── 08-어그리거트트랜잭션.md ├── 09-도메인모델과바운디드콘텍스트.md ├── 10-이벤트.md ├── 11-CQRS.md └── [1주차]01-02Chapter.md ├── Effective-Unit-Testing.md ├── Elegant-object ├── README.md ├── _00_birth.md ├── _01_education-1.md ├── _02_education-2.md ├── _03_employment-1.md ├── _04_employment-2.md └── _05_retire.md ├── Five Lines Of Code ├── 0장: Index.md ├── 1장: 리팩터링 리팩터링하기.md ├── 2장: 리팩터링 깊게 들여다보기.md ├── 3장: 긴 코드 조각내기.md ├── 4장: 타입 코드 처리하기.md ├── 5장: 유사한 코드 융합하기.md └── README.md ├── Java8 in Action ├── README.md ├── ch10-null대신Optional.md ├── ch12-새로운날짜와시간API.md ├── ch3-람다표현식.md ├── ch4-스트림소개.md ├── ch5-스트림활용.md ├── ch6-스트림으로데이터수집.md ├── ch7-병렬데이터처리와성능.md ├── ch8-리펙토링테스팅디버깅.md └── ch9-디폴트메서드.md ├── Pro react ├── README.md ├── [1]리액트의정의.md ├── [2]_시작하기.md ├── [3]DOM_추상화의_내부.md ├── [4]컴포넌트를_이용한_애플리케이션_구축.md ├── [5]정교한_상호작용.md ├── [6]라우팅.md └── [7]플럭스를_이용한_리액트_애플리케이션_설계.md ├── README.md ├── RxJava 프로그래밍 ├── Chapter02.md ├── Chapter03.md ├── Chapter04.md ├── Chapter05.md ├── Chapter06_RxAndroid.md ├── README.md ├── RxAndroidExample │ ├── .gitignore │ ├── .idea │ │ ├── caches │ │ │ └── build_file_checksums.ser │ │ ├── codeStyles │ │ │ └── Project.xml │ │ ├── gradle.xml │ │ ├── inspectionProfiles │ │ │ └── Project_Default.xml │ │ ├── markdown-navigator │ │ │ └── profiles_settings.xml │ │ ├── misc.xml │ │ └── runConfigurations.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── RxJava 3주차_또치.pdf ├── RxJava 4주차_가온.pdf ├── RxJava 6주차_디버깅과 예외처리-compressed.pdf ├── RxJavaStudy │ ├── .gitignore │ ├── .gradle │ │ ├── 4.0 │ │ │ ├── fileChanges │ │ │ │ └── last-build.bin │ │ │ └── fileHashes │ │ │ │ └── fileHashes.lock │ │ └── buildOutputCleanup │ │ │ ├── built.bin │ │ │ ├── cache.properties │ │ │ └── cache.properties.lock │ ├── .idea │ │ ├── compiler.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ ├── modules │ │ │ ├── RxJavaStudy_main.iml │ │ │ └── RxJavaStudy_test.iml │ │ └── vcs.xml │ ├── README.md │ ├── RxJavaStudy.iml │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── test │ │ └── java │ │ ├── Basic.java │ │ ├── CombinationOperator.java │ │ ├── ConnectableObservableTest.java │ │ ├── ConvertOperator.java │ │ ├── CreatorOperator.java │ │ ├── ObservableTest.java │ │ ├── OpenWeatherMapV1.java │ │ ├── OpenWeatherMapV2.java │ │ ├── ReduceTest.java │ │ ├── SingleTest.java │ │ ├── SubjectTest.java │ │ ├── Test.java │ │ └── common │ │ ├── CommonUtils.java │ │ ├── GsonHelper.java │ │ ├── Log.java │ │ ├── OkHttpHelper.java │ │ ├── Shape.java │ │ └── ShapeCannotFlipException.java └── chapter01.md ├── SQL AntiPatterns ├── README.md ├── code │ ├── 31-Flavors │ │ ├── anti │ │ │ ├── add-enum-value.sql │ │ │ ├── create-table-check.sql │ │ │ ├── create-table-enum.sql │ │ │ ├── distinct.sql │ │ │ ├── information-schema.sql │ │ │ └── remove-enum-value.sql │ │ ├── intro │ │ │ └── create-table.sql │ │ ├── obj │ │ │ └── insert-invalid.sql │ │ └── soln │ │ │ ├── create-lookup-table.sql │ │ │ ├── inactive.sql │ │ │ ├── insert-value.sql │ │ │ ├── query-canonical-values.sql │ │ │ ├── select-active.sql │ │ │ ├── update-inactive.sql │ │ │ └── update-value.sql │ ├── Diplomatic_immunity │ │ └── DatabaseTest.php │ ├── EAV │ │ ├── anti │ │ │ ├── count.sql │ │ │ ├── create-eav-table.sql │ │ │ ├── data-types.sql │ │ │ ├── foreign-key-eav.sql │ │ │ ├── foreign-key-plain.sql │ │ │ ├── insert-eav.sql │ │ │ ├── insert-plain.sql │ │ │ ├── query-eav.sql │ │ │ ├── query-plain.sql │ │ │ └── reconstruct.sql │ │ ├── intro │ │ │ └── count.sql │ │ └── soln │ │ │ ├── create-blob-tables.sql │ │ │ ├── create-class-tables.sql │ │ │ ├── create-concrete-tables.sql │ │ │ ├── create-sti-table.sql │ │ │ ├── insert-concrete.sql │ │ │ ├── post-process.php │ │ │ ├── post-process.sql │ │ │ ├── select-class.sql │ │ │ └── view-concrete.sql │ ├── Fear-Unknown │ │ ├── anti │ │ │ ├── equals-null.sql │ │ │ ├── expression.sql │ │ │ ├── parameter.sql │ │ │ ├── search-not.sql │ │ │ ├── search.sql │ │ │ ├── special-create-table.sql │ │ │ ├── special-insert.sql │ │ │ └── special-select.sql │ │ ├── intro │ │ │ ├── full-name.sql │ │ │ └── middle-name.sql │ │ └── soln │ │ │ ├── coalesce.sql │ │ │ ├── is-distinct-from-parameter.sql │ │ │ ├── is-distinct-from.sql │ │ │ └── search.sql │ ├── Groups │ │ ├── anti │ │ │ ├── distinct.sql │ │ │ ├── groupbyproduct.sql │ │ │ ├── maxandmin.sql │ │ │ └── sumbyproduct.sql │ │ ├── legit │ │ │ └── functional.sql │ │ └── soln │ │ │ ├── derived-table-no-duplicates.sql │ │ │ ├── derived-table.sql │ │ │ ├── extra-aggregate.sql │ │ │ ├── group-concat-mysql.sql │ │ │ ├── group-concat-pgsql.sql │ │ │ ├── notexists.sql │ │ │ └── outer-join.sql │ ├── ID-Required │ │ ├── anti │ │ │ ├── ambiguous.sql │ │ │ ├── id-redundant.sql │ │ │ ├── id-ubiquitous.sql │ │ │ ├── join.sql │ │ │ ├── select-max.sql │ │ │ └── superfluous.sql │ │ ├── intro │ │ │ └── articletags.sql │ │ └── soln │ │ │ ├── compound.sql │ │ │ ├── custom-primarykey.rb │ │ │ └── foreignkey-name.sql │ ├── Implicit-Columns │ │ ├── anti │ │ │ ├── add-column.sql │ │ │ ├── drop-column.sql │ │ │ ├── insert-mismatched.sql │ │ │ └── ordinal.php │ │ ├── intro │ │ │ ├── join-alias.sql │ │ │ └── join-wildcard.sql │ │ ├── legit │ │ │ └── wildcard-one-table.sql │ │ ├── obj │ │ │ ├── insert-explicit.sql │ │ │ ├── insert-implicit.sql │ │ │ ├── select-explicit.sql │ │ │ └── select-implicit.sql │ │ └── soln │ │ │ ├── insert-explicit.sql │ │ │ ├── select-explicit.sql │ │ │ └── yagni.sql │ ├── Index-Shotgun │ │ ├── anti │ │ │ ├── create-index.sql │ │ │ ├── create-table.sql │ │ │ ├── update-unindexed.sql │ │ │ └── update.sql │ │ └── soln │ │ │ └── explain.sql │ ├── Introduction │ │ ├── Makefile │ │ └── setup.sql │ ├── Jaywalking │ │ ├── anti │ │ │ ├── banana.sql │ │ │ ├── count.sql │ │ │ ├── create.sql │ │ │ ├── length.sql │ │ │ ├── regexp.sql │ │ │ ├── remove.php │ │ │ └── update.sql │ │ ├── obj │ │ │ └── create.sql │ │ └── soln │ │ │ ├── create.sql │ │ │ ├── group.sql │ │ │ ├── join.sql │ │ │ └── remove.sql │ ├── Keyless-Entry │ │ ├── anti │ │ │ ├── delete-child.sql │ │ │ ├── delete.sql │ │ │ ├── find-duplicates.sql │ │ │ ├── find-orphans.sql │ │ │ ├── insert.sql │ │ │ ├── set-default.sql │ │ │ └── update-catch22.sql │ │ └── soln │ │ │ ├── cascade.sql │ │ │ └── foreign-keys.sql │ ├── Magic-Beans │ │ ├── anti │ │ │ ├── anemic.php │ │ │ ├── crud.php │ │ │ └── doctrine.php │ │ └── soln │ │ │ └── domainmodel.php │ ├── Metadata-Tribbles │ │ ├── anti │ │ │ ├── alter-table.sql │ │ │ ├── anomaly.sql │ │ │ ├── check-constraint.sql │ │ │ ├── create-tables.sql │ │ │ ├── data-integrity.sql │ │ │ ├── foreign-key.sql │ │ │ ├── id-generator.sql │ │ │ ├── insert.sql │ │ │ ├── join-union.sql │ │ │ ├── multi-column.sql │ │ │ ├── synchronize.sql │ │ │ └── union.sql │ │ ├── intro │ │ │ ├── alter-table.sql │ │ │ └── create-table.sql │ │ └── soln │ │ │ ├── create-history-table.sql │ │ │ ├── horiz-partition.sql │ │ │ ├── separate-fixed-length.sql │ │ │ └── vert-partition.sql │ ├── Multi-Column │ │ ├── anti │ │ │ ├── add-tag-two-step.sql │ │ │ ├── add-tag.sql │ │ │ ├── alter-table.sql │ │ │ ├── create-table.sql │ │ │ ├── insert-duplicate.sql │ │ │ ├── remove-tag.sql │ │ │ ├── search-four-columns.sql │ │ │ ├── search-two-tags.sql │ │ │ ├── search.sql │ │ │ └── update.sql │ │ └── soln │ │ │ ├── create-table.sql │ │ │ ├── insert-delete.sql │ │ │ ├── search-two-tags.sql │ │ │ └── search.sql │ ├── Neat-Freak │ │ ├── anti │ │ │ ├── lowest-value.sql │ │ │ └── renumber.sql │ │ └── soln │ │ │ ├── row_number.sql │ │ │ └── uniqueidentifier-sql2005.sql │ ├── Normalization │ │ ├── 2NF-anti.sql │ │ ├── 2NF-normal.sql │ │ ├── 3NF-anti.sql │ │ ├── 4NF-anti.sql │ │ ├── 4NF-normal.sql │ │ ├── 5NF-anti.sql │ │ └── 5NF-normal.sql │ ├── Passwords │ │ ├── anti │ │ │ ├── auth-lumping.sql │ │ │ ├── auth-plaintext.sql │ │ │ ├── create-table.sql │ │ │ ├── insert-plaintext.sql │ │ │ └── select-plaintext.sql │ │ └── soln │ │ │ ├── auth-hash.sql │ │ │ ├── auth-salt.php │ │ │ ├── create-table.sql │ │ │ ├── dictionary-attack.sql │ │ │ ├── insert-hash.sql │ │ │ ├── reset-request.sql │ │ │ └── salt.sql │ ├── Phantom-Files │ │ ├── anti │ │ │ ├── create-accounts.sql │ │ │ ├── create-screenshots-path.sql │ │ │ ├── create-screenshots.sql │ │ │ ├── delete.sql │ │ │ ├── file-get.php │ │ │ ├── rollback.php │ │ │ └── transaction.php │ │ └── soln │ │ │ ├── binary-content.php │ │ │ ├── create-screenshots.sql │ │ │ ├── dumpfile.sql │ │ │ └── load-file.sql │ ├── Polymorphic │ │ ├── anti │ │ │ ├── addresses.sql │ │ │ ├── comments.sql │ │ │ └── select.sql │ │ ├── intro │ │ │ ├── comments.sql │ │ │ └── nonsense.sql │ │ ├── recog │ │ │ └── commentable.rb │ │ └── soln │ │ │ ├── reverse-coalesce.sql │ │ │ ├── reverse-join.sql │ │ │ ├── reverse-reference.sql │ │ │ ├── reverse-union.sql │ │ │ ├── reverse-unique.sql │ │ │ ├── super-join.sql │ │ │ └── super-table.sql │ ├── Random │ │ ├── anti │ │ │ ├── indexed-sort.sql │ │ │ └── orderby-rand.sql │ │ └── soln │ │ │ ├── limit-offset.php │ │ │ ├── next-higher.sql │ │ │ ├── rand-1-to-max.sql │ │ │ ├── rand-key-from-list.php │ │ │ ├── row_number.php │ │ │ ├── sample-oracle.sql │ │ │ └── tablesample-sql2005.sql │ ├── Rounding-Errors │ │ ├── anti │ │ │ ├── cumulative.sql │ │ │ ├── inexact.sql │ │ │ ├── magnify-rate.sql │ │ │ ├── select-rate.sql │ │ │ └── threshold.sql │ │ ├── intro │ │ │ ├── cost-per-bug.sql │ │ │ └── float-columns.sql │ │ └── soln │ │ │ ├── exact.sql │ │ │ ├── magnify-rate-exact.sql │ │ │ └── numeric-columns.sql │ ├── SQL-Injection │ │ ├── anti │ │ │ ├── delete.sql │ │ │ ├── ohare-escape.php │ │ │ ├── ohare-escape.sql │ │ │ ├── ohare.php │ │ │ ├── ohare.sql │ │ │ ├── parameter.php │ │ │ ├── parameter.sql │ │ │ ├── procedure.sql │ │ │ ├── set-password-escape.php │ │ │ ├── set-password-escape.sql │ │ │ ├── set-password.php │ │ │ └── set-password.sql │ │ ├── obj │ │ │ └── dynamic-sql.php │ │ └── soln │ │ │ ├── casting.php │ │ │ ├── filter.php │ │ │ ├── interpolate.php │ │ │ ├── mapping.php │ │ │ ├── orderby.sql │ │ │ ├── parameter-in.php │ │ │ ├── parameter.php │ │ │ ├── parameter.sql │ │ │ └── regexp.php │ ├── Search │ │ ├── anti │ │ │ ├── like-false-match.sql │ │ │ ├── like.sql │ │ │ ├── regexp-word.sql │ │ │ └── regexp.sql │ │ └── soln │ │ │ ├── inverted-index │ │ │ ├── create-table.sql │ │ │ ├── search-proc.sql │ │ │ └── trigger.sql │ │ │ ├── lucene │ │ │ ├── create-index.php │ │ │ └── search.php │ │ │ ├── microsoft │ │ │ ├── catalog.sql │ │ │ ├── create-index.sql │ │ │ ├── search.sql │ │ │ └── start.sql │ │ │ ├── mysql │ │ │ ├── alter-table.sql │ │ │ ├── match-boolean.sql │ │ │ └── match.sql │ │ │ ├── oracle │ │ │ ├── create-index.sql │ │ │ ├── ctxcat-create.sql │ │ │ ├── ctxcat-search.sql │ │ │ └── ctxxpath.sql │ │ │ ├── postgresql │ │ │ ├── create-index.sql │ │ │ ├── create-table.sql │ │ │ ├── search.sql │ │ │ └── trigger.sql │ │ │ ├── sphinx │ │ │ ├── indexer.sh │ │ │ ├── search.sh │ │ │ └── sphinx.conf │ │ │ └── sqlite │ │ │ ├── create-table.sql │ │ │ ├── insert.sql │ │ │ ├── makefile.in │ │ │ ├── search-boolean.sql │ │ │ └── search.sql │ ├── See-No-Evil │ │ ├── anti │ │ │ ├── no-check.php │ │ │ ├── white-space.php │ │ │ └── white-space.sql │ │ └── soln │ │ │ └── check.php │ ├── Spaghetti-Query │ │ ├── anti │ │ │ ├── cartesian-no-group.sql │ │ │ └── cartesian.sql │ │ ├── intro │ │ │ └── report.sql │ │ └── soln │ │ │ ├── bugs-by-customers.sql │ │ │ ├── bugs-per-developer.sql │ │ │ ├── count-developers.sql │ │ │ ├── count-products.sql │ │ │ ├── generate-update.sql │ │ │ ├── split-query.sql │ │ │ └── union.sql │ └── Trees │ │ ├── anti │ │ ├── adjacency-list.sql │ │ ├── all-comments.sql │ │ ├── ancestors.sql │ │ ├── delete-non-leaf.sql │ │ ├── delete-subtree.sql │ │ ├── insert.sql │ │ ├── parent.sql │ │ └── update.sql │ │ ├── intro │ │ └── parent.sql │ │ ├── legit │ │ ├── connect-by.sql │ │ └── cte.sql │ │ └── soln │ │ ├── closure-table │ │ ├── ancestors.sql │ │ ├── child.sql │ │ ├── create-table.sql │ │ ├── delete-leaf.sql │ │ ├── delete-subtree.sql │ │ ├── descendants.sql │ │ ├── insert.sql │ │ └── move-subtree.sql │ │ ├── nested-sets │ │ ├── ancestors.sql │ │ ├── create-table.sql │ │ ├── depth.sql │ │ ├── descendants.sql │ │ ├── insert.sql │ │ └── parent.sql │ │ └── path-enum │ │ ├── ancestors.sql │ │ ├── count.sql │ │ ├── create-table.sql │ │ ├── descendants.sql │ │ └── insert.sql └── setup.sql ├── Test-Driven-Development ├── .gitignore ├── Money 객체 만들기.md ├── README.md ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── test │ └── java │ └── Hello.java ├── UML실전에서는이것만쓴다 ├── README.md ├── [10] 상태 다이어그램.md ├── [11]휴리스틱과커피.md ├── [1]개요.md ├── [2]다이어그램으로작업하기.md ├── [3]클래스 다이어그램.md ├── [4]시퀀스다이어그램.md ├── [5]유스케이스.md ├── [6]객체지향 개발의 원칙.md ├── [8] 패키지.md ├── [9] 객체 다이어그램.md └── template.md ├── Working Effectively with Legacy Code ├── 1부_코드 변경의 매커니즘.md ├── 3부-의존관계제거기법.md ├── 9장_똑딱!테스트하네스에클래스제대로넣기.md ├── CH16_변경이 가능할 만큼 코드를 이해하지 못하는 경우.md ├── CH17_내 애플리케이션은 뼈대가 약하다.md ├── CH18_테스트 코드가 방해를 한다.md ├── CH19_내프로젝트는객체지향이아니다_어떻게안전하게변경할수있을까.md ├── CH20_이클래스는너무비대해서_더_이상_확장하고_싶지_않다.md ├── CH21-반복되는_동일한_수정,그만할_수는_없을까.md ├── CH22-괴물메서드를 변경해야하는데 테스트 코드를 작성하지 못하겠다.md ├── CH6_고칠것은많고시간은없고.md └── README.md ├── YOU-DON'T-KNOW-JS └── Type-Grammer │ ├── REFEREANCE.md │ ├── chapter1-타입.md │ ├── chapter10-스코프클로저.md │ ├── chapter2-값.md │ ├── chapter3-네이티브.md │ ├── chapter4-강제변환.md │ ├── chapter5-문법.md │ ├── chapter6-스코프.md │ ├── chapter8-함수vs블록스코프.md │ └── chapter9-호이스팅.md ├── _config.yml ├── asset ├── image-20241025073215384.png ├── image-20241025075102856.png ├── image-20241025075216018.png ├── image-20241025075553244.png ├── image-20241025080510228.png ├── image-20241025080520927.png ├── image-20241025081144309.png ├── image-20241025081233681.png ├── image-20241025081505978.png ├── image-20241025082538446.png ├── image-20241025082627905.png ├── image-20241025083659761.png ├── image-20241025090159987.png ├── image-20241026000546986.png ├── image-20241026000800907.png ├── image-20241026001531720.png ├── image-20241026001947693.png ├── image-20241026004238474.png ├── image-20241026004959185.png ├── image-20241026092259964.png ├── image-20241026092347651.png ├── image-20241026092423031.png ├── image-20241026092854892.png ├── image-20241026093411117.png ├── image-20241028101632477.png ├── image-20241028101941532.png ├── image-20241028102143396.png ├── image-20241028102417340.png ├── image-20241028102749892.png ├── image-20241028104941671.png ├── image-20241028104955121.png ├── image-20241028105237157.png ├── image-20241028105856732.png ├── image-20241028105938427.png ├── image-20241029125857965.png ├── image-20241029131052859.png ├── image-20241029134809824.png ├── image-20241029135030924.png ├── image-20241030204302345.png ├── image-20241030205122962.png └── image-20241030205235355.png ├── building-microservices └── README.md ├── clean-architecture ├── .gitattributes ├── .gitignore ├── .idea │ ├── .gitignore │ ├── aws.xml │ ├── codeStyles │ │ ├── Project.xml │ │ └── codeStyleConfig.xml │ ├── compiler.xml │ ├── gradle.xml │ ├── jarRepositories.xml │ ├── jpa-buddy.xml │ ├── misc.xml │ └── vcs.xml ├── README.md ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── main │ ├── java │ └── io │ │ └── reflectoring │ │ └── buckpal │ │ ├── BuckPalConfiguration.java │ │ ├── BuckPalConfigurationProperties.java │ │ ├── BuckpelApplication.java │ │ ├── MoneyTransferProperties.java │ │ └── account │ │ └── domain │ │ ├── Account.java │ │ ├── Activity.java │ │ ├── ActivityWindow.java │ │ └── Money.java │ └── resources │ └── application.yml ├── kotlinInAction ├── 1,2장_코틀린_기초.md ├── 4장_클래스_객체_인터페이스.md ├── 5장_람다로_프로그래밍.md ├── 6장_코틀린_타입_시스템.md ├── README.md ├── 고차 함수 파라미터와 반환 값으로 람다 사용.md └── 연산자 오버로딩과 기타 관례.md ├── microservice-pattern ├── 11장_프로덕션_레디_서비스개발_.pdf ├── 2-분해전략.md ├── 3-프로세스-간-통신.md ├── 4-트랜잭션관리:사가.md ├── 5-비지니스-로직-설계.md ├── 6-비지니스로직개발:이벤트소싱.md ├── 7-마이크로서비스 쿼리 구현.md ├── 8-외부 API 설계 이슈.md ├── 9-마이크로서비스테스트.md ├── API Composition과 CQRS.pdf └── README.md ├── monolith-to-microservices ├── 1_microservice.md ├── 2_결합도와_응집력.md ├── 3.1_마이그레이션_패턴_교살자_무화과-작성중.md └── 3_모놀리스를_그대로_둘_것인가?_바꿀_것인가?.md ├── objectdesignstyleguide ├── .gitignore ├── README.md ├── build.gradle ├── docs │ ├── 02-서비스-생성하기.md │ ├── 03-다른-객체-생성하기.md │ ├── 04-객체다루기.md │ ├── 05-객체-사용하기.md │ └── 06-정보-가져오기.md ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── push.py ├── the-design-of-web-apis ├── 5_직관적인_API디자인하기.md └── 6_예측_가능한_API_디자인하기.md ├── user-story ├── 10장_이터레이션_계획.md ├── 11장_속도_측정_및_모니터링.md ├── 12장_스토리가_아닌_것.md ├── 13장_왜_사용자_스토리인가?.md ├── 14장_스토리_냄새_카탈로그.md ├── 15장_스크럼에서_사용자_스토리_사용하기.md ├── 1장_개요.md ├── 2장_스토리_작성하기.md ├── 3장_사용자_역할_모델링.md ├── 4장_스토리_수집하기.md ├── 5장_대리사용자와_일하기.md ├── 6장_사용자스토리_인수_테스트.md ├── 7장_좋은_스토리를_위한_지침.md ├── 8장_사용자_스토리_추정.md ├── 9장_릴리즈_계획.md ├── README.md └── Untitled.md ├── 가상면접 사례로 배우는 대규모 시스템 설계 기초 ├── 10장-알림시스템설계.md ├── 13장-검색어자동완성시스템.md ├── 14장-유튜브 설계.md ├── 1장-사용자 수에 따른 규모 확장성.md ├── 2장-개략적인 규모 추정.md ├── 5장-안정해시설계-ppt.md ├── 5장-안정해시설계.md ├── 6장-키값저장소설계-ppt.md ├── 6장-키값저장소설계.md ├── 7장-분산시스템을위한유일ID생성기설계.md ├── 8장-URL 단축기 설계.md ├── 9장-웹크롤러설계.md ├── README.md ├── _6_gossip │ ├── .gitignore │ ├── .idea │ │ ├── .gitignore │ │ ├── gradle.xml │ │ ├── misc.xml │ │ ├── sonarlint │ │ │ ├── issuestore │ │ │ │ ├── 0 │ │ │ │ │ └── b │ │ │ │ │ │ └── 0ba1b9c7a4878802f938e331cc2d8a042087ec6b │ │ │ │ ├── c │ │ │ │ │ └── a │ │ │ │ │ │ └── ca008ce1ad5125494d92c1098a582d3287b5d915 │ │ │ │ ├── e │ │ │ │ │ ├── 1 │ │ │ │ │ │ └── e166e6e99e563ffa070e00997ec596a738baf5a9 │ │ │ │ │ └── c │ │ │ │ │ │ └── ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6 │ │ │ │ ├── f │ │ │ │ │ ├── 0 │ │ │ │ │ │ └── f07866736216be0ee2aba49e392191aeae700a35 │ │ │ │ │ ├── b │ │ │ │ │ │ └── fbe448ebfc3eb2d4e308f6b8b043666f5b57235e │ │ │ │ │ └── c │ │ │ │ │ │ └── fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10 │ │ │ │ └── index.pb │ │ │ └── securityhotspotstore │ │ │ │ ├── 0 │ │ │ │ └── b │ │ │ │ │ └── 0ba1b9c7a4878802f938e331cc2d8a042087ec6b │ │ │ │ ├── c │ │ │ │ └── a │ │ │ │ │ └── ca008ce1ad5125494d92c1098a582d3287b5d915 │ │ │ │ ├── e │ │ │ │ ├── 1 │ │ │ │ │ └── e166e6e99e563ffa070e00997ec596a738baf5a9 │ │ │ │ └── c │ │ │ │ │ └── ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6 │ │ │ │ ├── f │ │ │ │ ├── 0 │ │ │ │ │ └── f07866736216be0ee2aba49e392191aeae700a35 │ │ │ │ ├── b │ │ │ │ │ └── fbe448ebfc3eb2d4e308f6b8b043666f5b57235e │ │ │ │ └── c │ │ │ │ │ └── fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10 │ │ │ │ └── index.pb │ │ ├── uiDesigner.xml │ │ └── vcs.xml │ ├── build.gradle │ ├── config │ │ └── startup_members │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ └── java │ │ └── org │ │ └── example │ │ ├── Client.java │ │ ├── Main.java │ │ ├── Member.java │ │ └── TimeoutTimer.java ├── consistenthash │ ├── .gitignore │ ├── .idea │ │ ├── .gitignore │ │ ├── misc.xml │ │ └── vcs.xml │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── likelen │ │ ├── ConsistentHashRouter.java │ │ ├── HashFunction.java │ │ ├── Main.java │ │ ├── Node.java │ │ ├── VirtualNode.java │ │ └── sample │ │ ├── DistributionTestSample.java │ │ └── MyServiceNode.java ├── image-1.png ├── image-2.png └── image.png ├── 도메인주도설계-에릭에반스 ├── INTRO.md ├── README.md ├── _1.지식탐구.md ├── _10_유연한설계.md ├── _11_분석패턴의 적용.md ├── _12_모델과_디자인패턴의연결.md ├── _13_더심층적인통찰력을향한리팩터링.md ├── _2.의사소통과언어사용.md ├── _4.도메인의격리.md ├── _5.표현되는모델.md ├── _6.도메인객체의생명주기.md ├── _7_언어의사용.md ├── _8_더 심층적인 통찰력을 향한 리팩토링.md ├── _9_암시적인개념을 명확하게.md ├── 모델의 무결성 유지.md └── 서비스에 대해서.md ├── 모던자바인액션 ├── CHAPTER 15 CompletableFuture와 리액티브 프로그래밍 컨셉의 기초.md └── CHAPTER 16 CompletableFuture_안정적 비동기 프로그래밍.md ├── 반응형웹CSS ├── 1장.가변그리드.pdf ├── 3장.미디어쿼리와포트.pdf ├── 4장.플렉서블박스.pdf └── 반응형웹개요.pdf ├── 분산 컴퓨팅 ├── 1장 분산 컴퓨팅이란 무엇인가?.md ├── 2장 중계자와 2단계 커밋 프로토콜.md ├── 3장-시간동기화문제와논리적시계.md ├── 4장-CAP과 FLP정리.md └── README.md ├── 생각하는_프로그램 ├── README.md └── column1-조개껍질깨기.md ├── 소프트웨어설계의정석 └── 내용정리.md ├── 손에 잡히는 VIM.md ├── 실용주의 프로그래머(The Pragmenatic Programmer).md ├── 안드로이드-그한계를넘어서 ├── 18장.원격기기와_통신.md ├── 2.안드로이드를_위한_효과적인_자바_코드.md ├── 2_week.md ├── 3장_컴포넌트,매니페스트,리소스.md ├── 4장_안드로이드_사용자_경험_및_인터페이스_디자인.md ├── 5장_안드로이드_사용자_인터페이스_작업.md ├── 6장_서비스_및_백그라운드_작업.md ├── 7장_안드로이드IPC.md ├── 8장_브로드캐스트리시버.md ├── 9장_데이터_저장_및_직렬화.md ├── README.md └── 안드로이드테스트개요.md ├── 언카피어블(uncopyable) ├── README.md └── capture.md ├── 웹API설계원칙 ├── 1-3장.md └── README.md ├── 이펙티브 소프트웨어 테스팅(effective software testing) ├── 1장. 효율적이고 체계적인 소프트웨어 테스트.md ├── 2장. 명세 기반 테스트.md ├── 3장. 구조적 테스트와 코드 커버리지.md ├── 4장. 계약 설계.md ├── 5장. 속성 기반 테스트.md ├── 6장. 테스트 더블과 모의 객체.md ├── 7장. 테스트 가능성을 위한 설계.md ├── 8장. 테스트 주도 개발.md └── README.md ├── 자바 병렬 프로그래밍 ├── 10장-활동성을최대로높이기.md ├── 11장-성능.md ├── 12장-병렬프로그램테스트.md ├── 13장-명시적인락.md ├── 14장-동기화클래스구현.md ├── 15장-단일연산변수와넌블로킹동기화.md ├── 16장-자바메모리모델.md ├── 2장-스레드안전성.md ├── 3장-객체공유.md ├── 4장-객체구성.md ├── 5장-구성단위.md ├── 6장-작업실행.md ├── 7장-중단및종료.md ├── 8장-스레드폴활용.md ├── README.md └── img.png ├── 자바와-JUnit을-활용한-실용주의-단위테스트 ├── Pragmatic-unit-testing-in-java-with-junit │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ ├── main │ │ └── java │ │ │ ├── ch01 │ │ │ ├── ScoreCollection.java │ │ │ └── Scoreable.java │ │ │ ├── ch02 │ │ │ ├── Answer.java │ │ │ ├── Bool.java │ │ │ ├── BooleanQuestion.java │ │ │ ├── Criteria.java │ │ │ ├── Criterion.java │ │ │ ├── PercentileQuestion.java │ │ │ ├── Person.java │ │ │ ├── Profile.java │ │ │ ├── Question.java │ │ │ ├── ScoreCollection.java │ │ │ ├── Scoreable.java │ │ │ └── Weight.java │ │ │ └── ch16 │ │ │ ├── iloveyouboss │ │ │ ├── Answer.java │ │ │ ├── BearingOutOfRangeException.java │ │ │ ├── Bool.java │ │ │ ├── BooleanQuestion.java │ │ │ ├── Criteria.java │ │ │ ├── Criterion.java │ │ │ ├── PercentileQuestion.java │ │ │ ├── Person.java │ │ │ ├── Profile.java │ │ │ ├── ProfilePool.java │ │ │ ├── Question.java │ │ │ ├── ScoreCollection.java │ │ │ ├── Scoreable.java │ │ │ └── Weight.java │ │ │ ├── scratch │ │ │ ├── Bearing.java │ │ │ └── Rectangle.java │ │ │ ├── transmission │ │ │ ├── Car.java │ │ │ ├── Gear.java │ │ │ ├── Moveable.java │ │ │ └── Transmission.java │ │ │ └── util │ │ │ ├── InvariantException.java │ │ │ └── SparseArray.java │ │ └── test │ │ └── java │ │ ├── ch01 │ │ └── ScoreCollectionTest.java │ │ ├── ch02 │ │ └── ProfileTest.java │ │ └── ch16 │ │ ├── iloveyouboss │ │ ├── ProfilePoolTest.java │ │ ├── ProfileTest.java │ │ └── ScoreCollectionTest.java │ │ ├── scratch │ │ ├── AssertHamcrestTest.java │ │ ├── AssertMoreTest.java │ │ ├── AssertTest.java │ │ ├── BearingTest.java │ │ ├── ConstrainsSidesTo.java │ │ ├── ExpectToFail.java │ │ ├── NewtonTest.java │ │ ├── Point.java │ │ ├── PointMatcher.java │ │ └── RectangleTest.java │ │ ├── transmission │ │ └── TransmissionTest.java │ │ └── util │ │ └── SparseArrayTest.java └── docs │ ├── ch04-테스트-조직.md │ ├── ch05-FIRST.md │ ├── ch06-Right-BICEP.md │ └── ch08-깔끔한-코드로-리팩토링하기.md ├── 진화적 아키텍쳐(BuildingEvolutionaryArchitechtures) ├── CH1-진화적 소프트웨어 아키텍쳐.md ├── CH4-아키텍처 커버넌스 자동화.md ├── README.md └── Untitled.md ├── 켄트백의-구현패턴 ├── 1_개관.jpeg ├── 2_개관2.jpeg ├── 3_패턴.jpeg ├── 4_1_프로그래밍_이론.jpeg ├── 4_2_프로그래밍_이론.jpeg ├── 4_3_프로그래밍_이론.jpeg └── README.md ├── 코어논리학 ├── 1week_논증이란_무엇인가?.md ├── 1week_연습문제.md ├── 2week_연습문제.md ├── 2week_연역논증과_귀납논증.md ├── 4week_논리적연결사.md └── README.md ├── 패턴을_활용한_리팩토링 ├── 04장_코드_속에_냄새.md └── README.md └── 함수형사고(Functional Thinking) ├── FP_Book_Source ├── clojure │ ├── color_dispatch │ │ ├── core.clj │ │ └── core_test.clj │ ├── letter-grades │ │ ├── lettergrades.clj │ │ └── lettergradestest.clj │ ├── name-hash │ │ └── core.clj │ ├── number_classifier │ │ └── core.clj │ ├── palindromes │ │ └── palindromes.clj │ ├── primes │ │ └── core.clj │ ├── trans │ │ └── core.clj │ └── xml.clj ├── groovy │ └── com │ │ └── nealford │ │ └── ft │ │ ├── allaboutlists │ │ ├── AllAboutListsTest.groovy │ │ ├── LazyList.groovy │ │ └── NumberClassifier.groovy │ │ ├── as_demo.groovy │ │ ├── complexnums │ │ ├── ComplexNumber.groovy │ │ └── ComplexNumberTest.groovy │ │ ├── currying.groovy │ │ ├── flyweight │ │ └── FlyweightTest.groovy │ │ ├── lazy_primes │ │ └── LazyBuildup.groovy │ │ ├── list_perspective │ │ └── ListPerspectiveDemo.groovy │ │ ├── make_counter.groovy │ │ ├── memoization │ │ ├── ClassifierCached.groovy │ │ ├── ClassifierCachedSum.groovy │ │ ├── ClassifierMemoized.groovy │ │ ├── ClassifierMemoizedSum.groovy │ │ └── ClassifierTest.groovy │ │ ├── memoize_hashing │ │ ├── NameHash.groovy │ │ └── NameHashTest.groovy │ │ ├── metafunctionaljava │ │ └── IntegerClassifierTest.groovy │ │ ├── number_classifier │ │ ├── NumberClassifier.groovy │ │ └── NumberClassifierOpt.groovy │ │ ├── palindromes │ │ └── Palindromes.groovy │ │ ├── polydispatch │ │ ├── LetterGrade.groovy │ │ └── LetterGradeTest.groovy │ │ ├── simple_closure │ │ └── SimpleClosure.groovy │ │ ├── strategy │ │ └── StrategyTest.groovy │ │ ├── template │ │ ├── Customer.groovy │ │ ├── CustomerBlocks.groovy │ │ └── CustomerBlocksWithProtection.groovy │ │ └── trans │ │ └── TheCompanyProcess.groovy ├── java │ └── com │ │ └── nealford │ │ └── ft │ │ ├── 1_01_indexOfAny.java │ │ ├── CounterDemo.java │ │ ├── composition │ │ ├── ClassifierAlpha.java │ │ ├── ClassifierBeta.java │ │ ├── FClassifier.java │ │ ├── FPrime.java │ │ ├── Factors.java │ │ ├── FactorsBeta.java │ │ ├── PrimeAlpha.java │ │ └── PrimeBeta.java │ │ ├── errorhandling │ │ ├── Either.java │ │ ├── EitherTest.java │ │ ├── F.java │ │ ├── FjEitherTest.java │ │ ├── FjRomanNumeralParser.java │ │ ├── RomanNumeral.java │ │ └── RomanNumeralParser.java │ │ ├── number_classifier │ │ ├── ImpNumberClassifier.java │ │ ├── ImpNumberClassifierSimple.java │ │ ├── NumberClassifier.java │ │ └── NumberClassifierOptimized.java │ │ ├── number_classifier8 │ │ └── NumberClassifier.java │ │ ├── number_classifier_functional_java │ │ ├── NumberClassifier.java │ │ ├── NumberClassifierFJOptimized.java │ │ └── NumberStuff.java │ │ ├── number_classifier_totally_lazy │ │ └── NumberClassifier.java │ │ ├── primes │ │ ├── Prime.java │ │ └── PrimeIterator.java │ │ ├── structuralpatternmatching │ │ ├── Tree.java │ │ ├── TreeTest.java │ │ └── Trees.java │ │ ├── trans │ │ └── TheCompanyProcess.java │ │ ├── trans8 │ │ └── Process.java │ │ ├── wordfreq │ │ └── Words.java │ │ └── wordfreq8 │ │ └── Words.java ├── scala │ └── com │ │ └── nealford │ │ └── ft │ │ ├── Chap3.scala │ │ ├── complex_numbers │ │ ├── Complex.scala │ │ └── ComplexTest.scala │ │ ├── currying │ │ └── CurryTest.scala │ │ ├── indexOfAny │ │ └── indexOfAny.scala │ │ ├── letter_grades │ │ └── LetterGrade.scala │ │ ├── number_classifier │ │ └── NumberClassifier.scala │ │ ├── palimdromes │ │ └── Palindromes.scala │ │ ├── pattern_matching │ │ └── Colors.scala │ │ ├── trans │ │ └── Process.scala │ │ └── xml.scala └── src_list.html ├── Index.md ├── [1]왜.md ├── [2]전환.md ├── [3]양도하라.md ├── [4]열심히보다는_현명하게.md ├── [5]진화하라.md └── [6]전진하라.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/.DS_Store -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: make README.md 2 | 3 | on: 4 | pull_request: 5 | branches: [ master ] 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | python-version: [ 3.7 ] 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Set up Python 3.10 15 | uses: actions/setup-python@v3 16 | with: 17 | python-version: "3.10" 18 | - name: Install dependencies 19 | run: | 20 | python3 -m pip install --upgrade pip 21 | pip3 install requests 22 | - name: Run Python 23 | run: | 24 | python3 push.py ${{ secrets.TOKEN }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /github-api.ipynb 2 | /.idea/ 3 | .ipynb_checkpoints/ 4 | -------------------------------------------------------------------------------- /Clean Code/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | # Zeppelin ignored files 10 | /ZeppelinRemoteNotebooks/ 11 | -------------------------------------------------------------------------------- /Clean Code/.idea/Clean Code.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Clean Code/.idea/aws.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /Clean Code/.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /Clean Code/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /Clean Code/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Clean Code/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Clean Code/2장-의미 있는 이름.md: -------------------------------------------------------------------------------- 1 | # 의미 있는 이름이란? 2 | 3 | ## 인상 깊었던 내용 4 | 5 | **의도를 분명히 밝혀라** 6 | 의도를 분명히 밝힌다는 것은 무슨 의미인가? 어떻게 분명히 할 수 있는가? 좋은 이름으로 만드는 것이 첫번째이다. 7 | 8 | `코드는 단순성이 아니라 코드의 함축성이다.` 코드 맥락이 코드 자체에 명시적으로 드러나지 않는다. 9 | 10 | **그릇된 정보를 피하라** 11 | 일관성이 떨어지는 표기법은 `그릇된 정보`다. 12 | 13 | **의미 있게 구분하라** 14 | 15 | `getActiveAccount()` 16 | `getActiveAccounts()` 17 | `getActiveAccountInfo()` 18 | 19 | 어느 함수를 호출할지 어떻게 알까? 읽는 사람이 차이를 알도록 이름을 지어라. 20 | 21 | **한 개념에 한 단어를 사용하라** 22 | 추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다. 그러므로 일관성 있는 어휘를 사용해 의미 있는 이름을 표현하자. 23 | 24 | ## 왜 인상 깊었는지? 25 | 26 | 대다수 말하는 내용은 의미있는이름을 만들어야 하는 이유에 대해서 설명하고 있다고 생각된다. 좋은 내용임은 알지만, 현실 코딩에서 이 부분을 이해하고 사용할 수 있을까?여전히 쉽지 않은 문제이고, 의도적인 수련이 필요하다고 판단된다. 27 | 28 | 29 | ## 인상 깊었던 내용에 대해서 표현할 수 있는 코드 30 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/Chapter06_RxAndroid.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/Chapter06_RxAndroid.md -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | /app/ 12 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxAndroidExample/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.1.3' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxAndroidExample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 02 16:45:25 KST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxAndroidExample/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJava 3주차_또치.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxJava 3주차_또치.pdf -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJava 4주차_가온.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxJava 4주차_가온.pdf -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJava 6주차_디버깅과 예외처리-compressed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxJava 6주차_디버깅과 예외처리-compressed.pdf -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.gradle/4.0/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.gradle/4.0/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxJavaStudy/.gradle/4.0/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.gradle/buildOutputCleanup/built.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxJavaStudy/.gradle/buildOutputCleanup/built.bin -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 02 16:34:48 KST 2018 2 | gradle.version=4.0 3 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.gradle/buildOutputCleanup/cache.properties.lock: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/README.md: -------------------------------------------------------------------------------- 1 | # Goal 2 | 3 | #1. 4 | - Observable 클래스를 명확하게 이해합니다. 특히 뜨거운 Observable(Hot Observable)과 차가운 Observable(Cold Observable)의 개념을 꼭 이해 5 | - 간단한 예제로 map(), filter(), reduce(), flatMap() 함수의 사용법을 익힙니다. 6 | - 생성 연산자, 결합 연산자, 변환 연산자 등 카테고리별 주요 함수를 공부 7 | - 스케줄러의 의미를 배우고 subscribeOn()과 observeOn() 함수의 차이를 알아 둡니다. 8 | - 그 밖의 디버깅, 흐름 제어 함수를 익힌다. 9 | 10 | #2. 11 | Example Practice 12 | 13 | 14 | ​ 15 | ## Reference 16 | > 유동환님 저자의 RxJava 프로그래밍 17 | 18 | (유동환님의 허락 하에 일부 내용 정리중...) 19 | [LenKIM_TIL_자료](https://github.com/LenKIM/TIL_Today_I_Learned/tree/master/FP(FunctionalProgramming)/RxJAVA) -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxJavaStudy/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jul 06 23:10:43 KST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip 7 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'RxJavaStudy' 2 | 3 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/src/test/java/CombinationOperator.java: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/src/test/java/ReduceTest.java: -------------------------------------------------------------------------------- 1 | import io.reactivex.Maybe; 2 | import io.reactivex.Observable; 3 | import org.junit.Test; 4 | 5 | public class ReduceTest { 6 | 7 | @Test 8 | public void Testreduce() { 9 | 10 | String[] balls = {"1", "3", "5"}; 11 | Maybe source = Observable.fromArray(balls) 12 | .reduce((ball1, ball2) -> ball2 + "(" + ball1 + ")"); 13 | 14 | source.test().assertResult("5(3(1))"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/src/test/java/Test.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/RxJava 프로그래밍/RxJavaStudy/src/test/java/Test.java -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/src/test/java/common/GsonHelper.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | import com.google.gson.JsonParser; 4 | 5 | public class GsonHelper { 6 | public static String parseValue(String json, String key) { 7 | return new JsonParser().parse(json) 8 | .getAsJsonObject() 9 | .get(key) 10 | .getAsString(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /RxJava 프로그래밍/RxJavaStudy/src/test/java/common/ShapeCannotFlipException.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | public class ShapeCannotFlipException extends Exception { 4 | } 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/anti/add-enum-value.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs MODIFY COLUMN status 2 | ENUM('NEW', 'IN PROGRESS', 'FIXED', 'DUPLICATE'); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/anti/create-table-check.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | -- other columns 3 | status VARCHAR(20) CHECK (status IN ('NEW', 'IN PROGRESS', 'FIXED')) 4 | ); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/anti/create-table-enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | -- other columns 3 | status ENUM('NEW', 'IN PROGRESS', 'FIXED'), 4 | ); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/anti/distinct.sql: -------------------------------------------------------------------------------- 1 | SELECT DISTINCT status FROM Bugs; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/anti/information-schema.sql: -------------------------------------------------------------------------------- 1 | SELECT column_type 2 | FROM information_schema.columns 3 | WHERE table_schema = 'bugtracker_schema' 4 | AND table_name = 'bugs' 5 | AND column_name = 'status'; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/anti/remove-enum-value.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs MODIFY COLUMN status 2 | ENUM('NEW', 'IN PROGRESS', 'CODE COMPLETE', 'VERIFIED'); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/intro/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE PersonalContacts ( 2 | -- other columns 3 | salutation VARCHAR(4) 4 | CHECK (salutation IN ('Mr.', 'Mrs.', 'Ms.', 'Dr.', 'Rev.')), 5 | ); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/obj/insert-invalid.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Bugs (status) VALUES ('NEW'); -- OK 2 | 3 | INSERT INTO Bugs (status) VALUES ('BANANA'); -- Error! 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/soln/create-lookup-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugStatus ( 2 | status VARCHAR(20) PRIMARY KEY 3 | ); 4 | 5 | INSERT INTO BugStatus (status) VALUES ('NEW'), ('IN PROGRESS'), ('FIXED'); 6 | 7 | CREATE TABLE Bugs ( 8 | -- other columns 9 | status VARCHAR(20), 10 | FOREIGN KEY (status) REFERENCES BugStatus(status) 11 | ON UPDATE CASCADE 12 | ); 13 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/soln/inactive.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE BugStatus ADD COLUMN active 2 | ENUM('INACTIVE', 'ACTIVE') NOT NULL DEFAULT 'ACTIVE'; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/soln/insert-value.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO BugStatus (status) VALUES ('DUPLICATE'); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/soln/query-canonical-values.sql: -------------------------------------------------------------------------------- 1 | SELECT status FROM BugStatus ORDER BY status; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/soln/select-active.sql: -------------------------------------------------------------------------------- 1 | SELECT status FROM BugStatus WHERE active = 'ACTIVE'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/soln/update-inactive.sql: -------------------------------------------------------------------------------- 1 | UPDATE BugStatus SET active = 'INACTIVE' WHERE status = 'DUPLICATE'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/31-Flavors/soln/update-value.sql: -------------------------------------------------------------------------------- 1 | UPDATE BugStatus SET status = 'INVALID' WHERE status = 'BOGUS'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/count.sql: -------------------------------------------------------------------------------- 1 | SELECT date_reported, COUNT(*) AS bugs_per_date 2 | FROM (SELECT DISTINCT issue_id, attr_value AS date_reported 3 | FROM IssueAttributes 4 | WHERE attr_name IN ('date_reported', 'report_date')) 5 | GROUP BY date_reported; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/data-types.sql: -------------------------------------------------------------------------------- 1 | SELECT issue_id, COALESCE(attr_value_date, attr_value_datetime, 2 | attr_value_integer, attr_value_numeric, attr_value_float, 3 | attr_value_string, attr_value_text) AS "date_reported" 4 | FROM IssueAttributes 5 | WHERE attr_name = 'date_reported'; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/foreign-key-eav.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IssueAttributes ( 2 | issue_id BIGINT UNSIGNED NOT NULL, 3 | attr_name VARCHAR(100) NOT NULL, 4 | attr_value VARCHAR(100), 5 | FOREIGN KEY (attr_value) REFERENCES BugStatus(status) 6 | ); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/foreign-key-plain.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Issues ( 2 | issue_id SERIAL PRIMARY KEY, 3 | -- other columns 4 | status VARCHAR(20) NOT NULL DEFAULT 'NEW', 5 | FOREIGN KEY (status) REFERENCES BugStatus(status) 6 | ); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/insert-eav.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO IssueAttributes (issue_id, attr_name, attr_value) 2 | VALUES (1234, 'date_reported', 'banana'); -- Not an error! 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/insert-plain.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Issues (date_reported) VALUES ('banana'); -- ERROR! 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/query-eav.sql: -------------------------------------------------------------------------------- 1 | SELECT issue_id, attr_value AS "date_reported" 2 | FROM IssueAttributes 3 | WHERE attr_name = 'date_reported'; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/query-plain.sql: -------------------------------------------------------------------------------- 1 | SELECT issue_id, date_reported FROM Issues; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/anti/reconstruct.sql: -------------------------------------------------------------------------------- 1 | SELECT i.issue_id, 2 | i1.attr_value AS "date_reported", 3 | i2.attr_value AS "status", 4 | i3.attr_value AS "priority", 5 | i4.attr_value AS "description" 6 | FROM Issues AS i 7 | LEFT OUTER JOIN IssueAttributes AS i1 8 | ON i.issue_id = i1.issue_id AND i1.attr_name = 'date_reported' 9 | LEFT OUTER JOIN IssueAttributes AS i2 10 | ON i.issue_id = i2.issue_id AND i2.attr_name = 'status' 11 | LEFT OUTER JOIN IssueAttributes AS i3 12 | ON i.issue_id = i3.issue_id AND i3.attr_name = 'priority'; 13 | LEFT OUTER JOIN IssueAttributes AS i4 14 | ON i.issue_id = i4.issue_id AND i4.attr_name = 'description'; 15 | WHERE i.issue_id = 1234; 16 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/intro/count.sql: -------------------------------------------------------------------------------- 1 | SELECT date_reported, COUNT(*) 2 | FROM Bugs 3 | GROUP BY date_reported; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/soln/create-blob-tables.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Issues ( 2 | issue_id SERIAL PRIMARY KEY, 3 | reported_by BIGINT UNSIGNED NOT NULL, 4 | product_id BIGINT UNSIGNED, 5 | priority VARCHAR(20), 6 | version_resolved VARCHAR(20), 7 | status VARCHAR(20), 8 | issue_type VARCHAR(10), -- BUG or FEATURE 9 | attributes TEXT NOT NULL, -- all dynamic attributes for the row 10 | FOREIGN KEY (reported_by) REFERENCES Accounts(account_id), 11 | FOREIGN KEY (product_id) REFERENCES Products(product_id) 12 | ); 13 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/soln/create-sti-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Issues ( 2 | issue_id SERIAL PRIMARY KEY, 3 | reported_by BIGINT UNSIGNED NOT NULL, 4 | product_id BIGINT UNSIGNED, 5 | priority VARCHAR(20), 6 | version_resolved VARCHAR(20), 7 | status VARCHAR(20), 8 | issue_type VARCHAR(10), -- BUG or FEATURE 9 | severity VARCHAR(20), -- only for bugs 10 | version_affected VARCHAR(20), -- only for bugs 11 | sponsor VARCHAR(50), -- only for feature requests 12 | FOREIGN KEY (reported_by) REFERENCES Accounts(account_id) 13 | FOREIGN KEY (product_id) REFERENCES Products(product_id) 14 | ); 15 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/soln/insert-concrete.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO FeatureRequests (issue_id, severity) VALUES ( ... ); -- ERROR! 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/soln/post-process.php: -------------------------------------------------------------------------------- 1 | query( 5 | "SELECT issue_id, attr_name, attr_value 6 | FROM IssueAttributes 7 | WHERE issue_id = 1234"); 8 | while ($row = $stmt->fetch()) { 9 | $id = $row['issue_id']; 10 | $field = $row['attr_name']; 11 | $value = $row['attr_value']; 12 | if (!array_key_exists($id, $objects)) { 13 | $objects[$id] = new stdClass(); 14 | } 15 | $objects[$id]->$field = $value; 16 | } 17 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/soln/post-process.sql: -------------------------------------------------------------------------------- 1 | SELECT issue_id, attr_name, attr_value 2 | FROM IssueAttributes 3 | WHERE issue_id = 1234; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/soln/select-class.sql: -------------------------------------------------------------------------------- 1 | SELECT i.*, b.*, f.* 2 | FROM Issues AS i 3 | LEFT OUTER JOIN Bugs AS b USING (issue_id) 4 | LEFT OUTER JOIN FeatureRequests AS f USING (issue_id); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/EAV/soln/view-concrete.sql: -------------------------------------------------------------------------------- 1 | CREATE VIEW Issues AS 2 | SELECT b.issue_id, b.reported_by, ... 'bug' AS issue_type 3 | FROM Bugs AS b 4 | UNION ALL 5 | SELECT f.issue_id, f.reported_by, ... 'feature' AS issue_type 6 | FROM FeatureRequests AS f; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/equals-null.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE assigned_to = NULL; 2 | 3 | SELECT * FROM Bugs WHERE assigned_to <> NULL; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/expression.sql: -------------------------------------------------------------------------------- 1 | SELECT hours + 10 FROM Bugs; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/parameter.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE assigned_to = ?; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/search-not.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE NOT (assigned_to = 123); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/search.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE assigned_to = 123; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/special-create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id SERIAL PRIMARY KEY, 3 | -- other columns 4 | assigned_to BIGINT UNSIGNED NOT NULL, 5 | hours NUMERIC(9,2) NOT NULL, 6 | FOREIGN KEY (assigned_to) REFERENCES Accounts(account_id) 7 | ); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/special-insert.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Bugs (assigned_to, hours) VALUES (-1, -1); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/anti/special-select.sql: -------------------------------------------------------------------------------- 1 | SELECT AVG( hours ) AS average_hours_per_bug FROM Bugs 2 | WHERE hours <> -1; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/intro/full-name.sql: -------------------------------------------------------------------------------- 1 | SELECT first_name || ' ' || last_name AS full_name FROM Accounts; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/intro/middle-name.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Accounts ADD COLUMN middle_initial CHAR(2); 2 | 3 | UPDATE Accounts SET middle_initial = 'J.' WHERE account_id = 123; 4 | UPDATE Accounts SET middle_initial = 'C.' WHERE account_id = 321; 5 | 6 | SELECT first_name || ' ' || middle_initial || ' ' || last_name AS full_name 7 | FROM Accounts; 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/soln/coalesce.sql: -------------------------------------------------------------------------------- 1 | SELECT first_name || COALESCE(' ' || middle_initial || ' ', ' ') || last_name 2 | AS full_name 3 | FROM Accounts; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/soln/is-distinct-from-parameter.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE assigned_to IS DISTINCT FROM ?; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/soln/is-distinct-from.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE assigned_to IS NULL OR assigned_to <> 1; 2 | 3 | SELECT * FROM Bugs WHERE assigned_to IS DISTINCT FROM 1; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Fear-Unknown/soln/search.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE assigned_to IS NULL; 2 | 3 | SELECT * FROM Bugs WHERE assigned_to IS NOT NULL; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/anti/distinct.sql: -------------------------------------------------------------------------------- 1 | -- START:distinct 2 | SELECT DISTINCT date_reported, reported_by FROM Bugs; 3 | -- END:distinct 4 | -- START:groupby 5 | SELECT date_reported, reported_by FROM Bugs 6 | GROUP BY date_reported, reported_by; 7 | -- END:groupby 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/anti/groupbyproduct.sql: -------------------------------------------------------------------------------- 1 | -- START:standard 2 | SELECT product_id, MAX(date_reported) AS latest 3 | FROM Bugs JOIN BugsProducts USING (bug_id) 4 | GROUP BY product_id; 5 | -- END:standard 6 | -- START:withbugid 7 | SELECT product_id, MAX(date_reported) AS latest, bug_id 8 | FROM Bugs JOIN BugsProducts USING (bug_id) 9 | GROUP BY product_id; 10 | -- END:withbugid 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/anti/maxandmin.sql: -------------------------------------------------------------------------------- 1 | SELECT product_id, MAX(date_reported) AS latest, 2 | MIN(date_reported) AS earliest, bug_id 3 | FROM Bugs JOIN BugsProducts USING (bug_id) 4 | GROUP BY product_id; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/anti/sumbyproduct.sql: -------------------------------------------------------------------------------- 1 | SELECT product_id, SUM(hours) AS total_project_estimate, bug_id 2 | FROM Bugs JOIN BugsProducts USING (bug_id) 3 | GROUP BY product_id; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/legit/functional.sql: -------------------------------------------------------------------------------- 1 | SELECT b.reported_by, a.account_name 2 | FROM Bugs b JOIN Accounts a ON (b.reported_by = a.account_id) 3 | GROUP BY b.reported_by; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/soln/derived-table-no-duplicates.sql: -------------------------------------------------------------------------------- 1 | SELECT m.product_id, m.latest, MAX(b1.bug_id) AS latest_bug_id 2 | FROM Bugs b1 JOIN 3 | (SELECT product_id, MAX(date_reported) AS latest 4 | FROM Bugs b2 JOIN BugsProducts USING (bug_id) 5 | GROUP BY product_id) m 6 | ON (b1.date_reported = m.latest) 7 | GROUP BY m.product_id, m.latest; 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/soln/derived-table.sql: -------------------------------------------------------------------------------- 1 | SELECT m.product_id, m.latest, b1.bug_id 2 | FROM Bugs b1 JOIN BugsProducts bp1 USING (bug_id) 3 | JOIN (SELECT bp2.product_id, MAX(b2.date_reported) AS latest 4 | FROM Bugs b2 JOIN BugsProducts bp2 USING (bug_id) 5 | GROUP BY bp2.product_id) m 6 | ON (bp1.product_id = m.product_id AND b1.date_reported = m.latest); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/soln/extra-aggregate.sql: -------------------------------------------------------------------------------- 1 | SELECT product_id, MAX(date_reported) AS latest, 2 | MAX(bug_id) AS latest_bug_id 3 | FROM Bugs JOIN BugsProducts USING (bug_id) 4 | GROUP BY product_id; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/soln/group-concat-mysql.sql: -------------------------------------------------------------------------------- 1 | SELECT product_id, MAX(date_reported) AS latest 2 | GROUP_CONCAT(bug_id) AS bug_id_list, 3 | FROM Bugs JOIN BugsProducts USING (bug_id) 4 | GROUP BY product_id; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/soln/group-concat-pgsql.sql: -------------------------------------------------------------------------------- 1 | CREATE AGGREGATE GROUP_ARRAY ( 2 | BASETYPE = ANYELEMENT, 3 | SFUNC = ARRAY_APPEND, 4 | STYPE = ANYARRAY, 5 | INITCOND = '{}' 6 | ); 7 | 8 | SELECT product_id, MAX(date_reported) AS latest, 9 | ARRAY_TO_STRING(GROUP_ARRAY(bug_id), ',') AS bug_id_list 10 | FROM Bugs JOIN BugsProducts USING (bug_id) 11 | GROUP BY product_id; 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/soln/notexists.sql: -------------------------------------------------------------------------------- 1 | SELECT bp1.product_id, b1.date_reported AS latest, b1.bug_id 2 | FROM Bugs b1 JOIN BugsProducts bp1 USING (bug_id) 3 | WHERE NOT EXISTS 4 | (SELECT * FROM Bugs b2 JOIN BugsProducts bp2 USING (bug_id) 5 | WHERE bp1.product_id = bp2.product_id 6 | AND b1.date_reported < b2.date_reported); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Groups/soln/outer-join.sql: -------------------------------------------------------------------------------- 1 | SELECT bp1.product_id, b1.date_reported AS latest, b1.bug_id 2 | FROM Bugs b1 JOIN BugsProducts bp1 ON (b1.bug_id = bp1.bug_id) 3 | LEFT OUTER JOIN (Bugs AS b2 JOIN BugsProducts AS bp2 ON (b2.bug_id = bp2.bug_id)) 4 | ON (bp1.product_id = bp2.product_id AND (b1.date_reported < b2.date_reported 5 | OR b1.date_reported = b2.date_reported AND b1.bug_id < b2.bug_id)) 6 | WHERE b2.bug_id IS NULL; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/anti/ambiguous.sql: -------------------------------------------------------------------------------- 1 | SELECT b.id, a.id 2 | FROM Bugs b 3 | JOIN Accounts a ON (b.assigned_to = a.id) 4 | WHERE b.status = 'OPEN'; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/anti/id-redundant.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | id SERIAL PRIMARY KEY, 3 | bug_id VARCHAR(10) UNIQUE, 4 | description VARCHAR(1000), 5 | -- . . . 6 | ); 7 | 8 | INSERT INTO Bugs (bug_id, description, ...) 9 | VALUES ('VIS-078', 'crashes on save', ...); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/anti/id-ubiquitous.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | id SERIAL PRIMARY KEY, 3 | description VARCHAR(1000), 4 | -- . . . 5 | ); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/anti/join.sql: -------------------------------------------------------------------------------- 1 | -- START:on 2 | SELECT * FROM Bugs AS b JOIN BugsProducts AS bp ON (b.bug_id = bp.bug_id); 3 | -- END:on 4 | -- START:using 5 | SELECT * FROM Bugs JOIN BugsProducts USING (bug_id); 6 | -- END:using 7 | -- START:verbose 8 | SELECT * FROM Bugs AS b JOIN BugsProducts AS bp ON (b.id = bp.bug_id); 9 | -- END:vebose 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/anti/select-max.sql: -------------------------------------------------------------------------------- 1 | SELECT MAX(bug_id) + 1 AS next_bug_id FROM Bugs; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/intro/articletags.sql: -------------------------------------------------------------------------------- 1 | -- START:table 2 | CREATE TABLE ArticleTags ( 3 | id SERIAL PRIMARY KEY, 4 | article_id BIGINT UNSIGNED NOT NULL, 5 | tag_id BIGINT UNSIGNED NOT NULL, 6 | FOREIGN KEY (article_id) REFERENCES Articles (id), 7 | FOREIGN KEY (tag_id) REFERENCES Tags (id) 8 | ); 9 | -- END:table 10 | -- START:select 11 | SELECT tag_id, COUNT(*) AS articles_per_tag FROM ArticleTags WHERE tag_id = 327; 12 | -- END:select 13 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/soln/compound.sql: -------------------------------------------------------------------------------- 1 | -- START:table 2 | CREATE TABLE BugsProducts ( 3 | bug_id BIGINT UNSIGNED NOT NULL, 4 | product_id BIGINT UNSIGNED NOT NULL, 5 | PRIMARY KEY (bug_id, product_id), 6 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 7 | FOREIGN KEY (product_id) REFERENCES Products(product_id) 8 | ); 9 | -- END:table 10 | 11 | -- START:insert 12 | INSERT INTO BugsProducts (bug_id, product_id) 13 | VALUES (1234, 1), (1234, 2), (1234, 3); 14 | 15 | INSERT INTO BugsProducts (bug_id, product_id) 16 | VALUES (1234, 1); -- error: duplicate entry 17 | --END:insert 18 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/soln/custom-primarykey.rb: -------------------------------------------------------------------------------- 1 | #--- 2 | # Excerpted from "SQL Antipatterns", 3 | # published by The Pragmatic Bookshelf. 4 | # Copyrights apply to this code. It may not be used to create training material, 5 | # courses, books, articles, and the like. Contact us if you are in doubt. 6 | # We make no guarantees that this code is fit for any purpose. 7 | # Visit http://www.pragmaticprogrammer.com/titles/bksqla for more book information. 8 | #--- 9 | class Bug < ActiveRecord::Base 10 | set_primary_key "bug_id" 11 | end 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/ID-Required/soln/foreignkey-name.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | -- . . . 3 | reported_by BIGINT UNSIGNED NOT NULL, 4 | FOREIGN KEY (reported_by) REFERENCES Accounts(account_id) 5 | ); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/anti/add-column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs ADD COLUMN date_due DATE; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/anti/drop-column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs DROP COLUMN verified_by; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/anti/insert-mismatched.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Bugs VALUES (DEFAULT, CURDATE(), 'New bug', 'Test T987 fails...', 2 | NULL, 123, NULL, NULL, DEFAULT, 'Medium', NULL); 3 | 4 | -- SQLSTATE 21S01: Column count doesn't match value count at row 1 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/anti/ordinal.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM Bugs WHERE bug_id = 1234"); 3 | $row = $stmt->fetch(); 4 | $hours = $row[10]; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/intro/join-alias.sql: -------------------------------------------------------------------------------- 1 | SELECT b.title, a.title AS salutation 2 | FROM Books b JOIN Authors a ON (b.author_id = a.author_id); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/intro/join-wildcard.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Books b JOIN Authors a ON (b.author_id = a.author_id); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/legit/wildcard-one-table.sql: -------------------------------------------------------------------------------- 1 | SELECT b.*, a.first_name, a.email 2 | FROM Bugs b JOIN Accounts a 3 | ON (b.reported_by = a.account_id); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/obj/insert-explicit.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Accounts (account_name, first_name, last_name, email, 2 | password, portrait_image, hourly_rate) VALUES 3 | ('bkarwin', 'Bill', 'Karwin', 'bill@example.com', SHA2('xyzzy'), NULL, 49.95); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/obj/insert-implicit.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Accounts VALUES (DEFAULT, 2 | 'bkarwin', 'Bill', 'Karwin', 'bill@example.com', SHA2('xyzzy'), NULL, 49.95); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/obj/select-explicit.sql: -------------------------------------------------------------------------------- 1 | SELECT bug_id, date_reported, summary, description, resolution, 2 | reported_by, assigned_to, verified_by, status, priority, hours 3 | FROM Bugs; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/obj/select-implicit.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/soln/insert-explicit.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Accounts (account_name, first_name, last_name, email, 2 | password_hash, portrait_image, hourly_rate) 3 | VALUES ('bkarwin', 'Bill', 'Karwin', 'bill@example.com', 4 | SHA2('xyzzy'), NULL, 49.95); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/soln/select-explicit.sql: -------------------------------------------------------------------------------- 1 | SELECT bug_id, date_reported, summary, description, resolution, 2 | reported_by, assigned_to, verified_by, status, priority, hours 3 | FROM Bugs; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Implicit-Columns/soln/yagni.sql: -------------------------------------------------------------------------------- 1 | SELECT date_reported, summary, description, resolution, status, priority 2 | FROM Bugs; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Index-Shotgun/anti/create-index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX TelephoneBook ON Accounts(last_name, first_name); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Index-Shotgun/anti/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id SERIAL PRIMARY KEY, 3 | date_reported DATE NOT NULL, 4 | summary VARCHAR(80) NOT NULL, 5 | status VARCHAR(10) NOT NULL, 6 | hours NUMERIC(9,2), 7 | INDEX (bug_id), -- (1) 8 | INDEX (summary), -- (2) 9 | INDEX (hours), -- (3) 10 | INDEX (bug_id, date_reported, status) -- (4) 11 | ); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Index-Shotgun/anti/update-unindexed.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs SET status = 'OBSOLETE' WHERE date_reported < '2000-01-01'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Index-Shotgun/anti/update.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs SET status = 'FIXED' WHERE bug_id = 1234; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Index-Shotgun/soln/explain.sql: -------------------------------------------------------------------------------- 1 | EXPLAIN SELECT Bugs.* 2 | FROM Bugs 3 | JOIN (BugsProducts JOIN Products USING (product_id)) 4 | USING (bug_id) 5 | WHERE summary LIKE '%crash%' 6 | AND product_name = 'Open RoundFile' 7 | ORDER BY date_reported DESC; 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Introduction/Makefile: -------------------------------------------------------------------------------- 1 | MYSQL=/opt/local/bin/mysql5 2 | USER= 3 | PASS= 4 | DB=test 5 | MYSQLCMD=$(MYSQL) -u$(USER) -p$(PASS) $(DB) --verbose 6 | 7 | all: setup 8 | 9 | setup: 10 | $(MYSQLCMD) -e "source setup.sql" 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/anti/banana.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Products (product_id, product_name, account_id) 2 | VALUES (DEFAULT, 'Visual TurboBuilder', '12,34,banana'); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/anti/count.sql: -------------------------------------------------------------------------------- 1 | SELECT product_id, LENGTH(account_id) - LENGTH(REPLACE(account_id, ',', '')) + 1 2 | AS contacts_per_product 3 | FROM Products; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/anti/create.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Products ( 2 | product_id SERIAL PRIMARY KEY, 3 | product_name VARCHAR(1000), 4 | account_id VARCHAR(100), -- comma-separated list 5 | -- . . . 6 | ); 7 | 8 | INSERT INTO Products (product_id, product_name, account_id) 9 | VALUES (DEFAULT, 'Visual TurboBuilder', '12,34'); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/anti/length.sql: -------------------------------------------------------------------------------- 1 | UPDATE Products SET account_id = '10,14,18,22,26,30,34,38,42,46' 2 | WHERE product_id = 123; 3 | 4 | UPDATE Products SET account_id = '101418,222630,343842,467790' 5 | WHERE product_id = 123; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/anti/regexp.sql: -------------------------------------------------------------------------------- 1 | -- START:where 2 | SELECT * FROM Products WHERE account_id REGEXP '[[:<:]]12[[:>:]]'; 3 | -- END:where 4 | -- START:join 5 | SELECT * FROM Products AS p JOIN Accounts AS a 6 | ON p.account_id REGEXP '[[:<:]]' || a.account_id || '[[:>:]]' 7 | WHERE p.product_id = 123; 8 | -- END:join 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/anti/remove.php: -------------------------------------------------------------------------------- 1 | query( 4 | "SELECT account_id FROM Products WHERE product_id = 123"); 5 | $row = $stmt->fetch(); 6 | $contact_list = $row['account_id']; 7 | 8 | // change list in PHP code 9 | $value_to_remove = "34"; 10 | $contact_list = split(",", $contact_list); 11 | $key_to_remove = array_search($value_to_remove, $contact_list); 12 | unset($contact_list[$key_to_remove]); 13 | $contact_list = join(",", $contact_list); 14 | 15 | $stmt = $pdo->prepare( 16 | "UPDATE Products SET account_id = ? 17 | WHERE product_id = 123"); 18 | $stmt->execute(array($contact_list)); 19 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/anti/update.sql: -------------------------------------------------------------------------------- 1 | UPDATE Products 2 | SET account_id = account_id || ',' || 56 3 | WHERE product_id = 123; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/obj/create.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Products ( 2 | product_id SERIAL PRIMARY KEY, 3 | product_name VARCHAR(1000), 4 | account_id BIGINT UNSIGNED, 5 | -- . . . 6 | FOREIGN KEY (account_id) REFERENCES Accounts(account_id) 7 | ); 8 | 9 | INSERT INTO Products (product_id, product_name, account_id) 10 | VALUES (DEFAULT, 'Visual TurboBuilder', 12); 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/soln/create.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Contacts ( 2 | product_id BIGINT UNSIGNED NOT NULL, 3 | account_id BIGINT UNSIGNED NOT NULL, 4 | PRIMARY KEY (product_id, account_id), 5 | FOREIGN KEY (product_id) REFERENCES Products(product_id), 6 | FOREIGN KEY (account_id) REFERENCES Accounts(account_id) 7 | ); 8 | 9 | INSERT INTO Contacts (product_id, account_id) 10 | VALUES (123, 12), (123, 34), (345, 23), (567, 12), (567, 34); 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/soln/group.sql: -------------------------------------------------------------------------------- 1 | -- START:accountsperproduct 2 | SELECT product_id, COUNT(*) AS accounts_per_product 3 | FROM Contacts 4 | GROUP BY product_id; 5 | -- END:accountsperproduct 6 | -- START:productsperaccount 7 | SELECT account_id, COUNT(*) AS products_per_account 8 | FROM Contacts 9 | GROUP BY account_id; 10 | -- END:productsperaccount 11 | -- START:productwithmaxaccounts 12 | SELECT c.product_id, c.contacts_per_product 13 | FROM ( 14 | SELECT product_id, COUNT(*) AS accounts_per_product 15 | FROM Contacts 16 | GROUP BY product_id 17 | ) AS c 18 | ORDER BY c.contacts_per_product DESC LIMIT 1 19 | -- END:productwithmaxaccounts 20 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/soln/join.sql: -------------------------------------------------------------------------------- 1 | -- START:productbyaccount 2 | SELECT p.* 3 | FROM Products AS p JOIN Contacts AS c ON (p.product_id = c.product_id) 4 | WHERE c.account_id = 34; 5 | -- END:productbyaccount 6 | -- START:accountbyproduct 7 | SELECT a.* 8 | FROM Accounts AS a JOIN Contacts AS c ON (a.account_id = c.account_id) 9 | WHERE c.product_id = 123; 10 | -- END:accountbyproduct 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Jaywalking/soln/remove.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Contacts (product_id, account_id) VALUES (456, 34); 2 | 3 | DELETE FROM Contacts WHERE product_id = 456 AND account_id = 34; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/anti/delete-child.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM BugStatus WHERE status = 'BOGUS'; -- ERROR! 2 | DELETE FROM Bugs WHERE status = 'BOGUS'; 3 | DELETE FROM BugStatus WHERE status = 'BOGUS'; -- retry succeeds 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/anti/delete.sql: -------------------------------------------------------------------------------- 1 | -- START:select 2 | SELECT bug_id FROM Bugs WHERE reported_by = 1; 3 | -- END:select 4 | -- START:delete 5 | DELETE FROM Accounts WHERE account_id = 1; 6 | -- END:delete 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/anti/find-duplicates.sql: -------------------------------------------------------------------------------- 1 | SELECT bug_id FROM Bugs GROUP BY bug_id HAVING COUNT(*) > 1; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/anti/find-orphans.sql: -------------------------------------------------------------------------------- 1 | SELECT b.bug_id, b.status 2 | FROM Bugs b LEFT OUTER JOIN BugStatus s 3 | ON (b.status = s.status) 4 | WHERE s.status IS NULL; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/anti/insert.sql: -------------------------------------------------------------------------------- 1 | -- START:select 2 | SELECT account_id FROM Accounts WHERE account_id = 1; 3 | -- END:select 4 | -- START:insert 5 | INSERT INTO Bugs (reported_by) VALUES (1); 6 | -- END:insert 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/anti/set-default.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs SET status = DEFAULT WHERE status = 'BANANA'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/anti/update-catch22.sql: -------------------------------------------------------------------------------- 1 | UPDATE BugStatus SET status = 'INVALID' WHERE status = 'BOGUS'; -- ERROR! 2 | 3 | UPDATE Bugs SET status = 'INVALID' WHERE status = 'BOGUS'; -- ERROR! 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/soln/cascade.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | -- . . . 3 | reported_by BIGINT UNSIGNED NOT NULL, 4 | status VARCHAR(20) NOT NULL DEFAULT 'NEW', 5 | FOREIGN KEY (reported_by) REFERENCES Accounts(account_id) 6 | ON UPDATE CASCADE 7 | ON DELETE RESTRICT, 8 | FOREIGN KEY (status) REFERENCES BugStatus(status) 9 | ON UPDATE CASCADE 10 | ON DELETE SET DEFAULT 11 | ); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Keyless-Entry/soln/foreign-keys.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | -- . . . 3 | reported_by BIGINT UNSIGNED NOT NULL, 4 | status VARCHAR(20) NOT NULL DEFAULT 'NEW', 5 | FOREIGN KEY (reported_by) REFERENCES Accounts(account_id), 6 | FOREIGN KEY (status) REFERENCES BugStatus(status) 7 | ); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Magic-Beans/anti/crud.php: -------------------------------------------------------------------------------- 1 | assigned_to = $a->account_id; 7 | $this->save(); 8 | mail($a->email, "Assigned bug", 9 | "You are now responsible for bug #{$this->bug_id}."); 10 | } 11 | } 12 | $bugsTable = Doctrine_Core::getTable('Bugs'); 13 | $bug = $bugsTable->find(1234); 14 | $bug->assigned_to = $user->account_id; 15 | $bug->save(); 16 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Magic-Beans/anti/doctrine.php: -------------------------------------------------------------------------------- 1 | find(1234); 4 | 5 | $bug = new Bugs(); 6 | $bug->summary = "Crashes when I save"; 7 | $bug->save(); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/alter-table.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs_2010 ADD COLUMN hours NUMERIC(9,2); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/anomaly.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs_2010 2 | SET date_reported = '2009-12-27' 3 | WHERE bug_id = 1234; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/check-constraint.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs_2009 ( 2 | -- other columns 3 | date_reported DATE CHECK (EXTRACT(YEAR FROM date_reported) = 2009) 4 | ); 5 | 6 | CREATE TABLE Bugs_2010 ( 7 | -- other columns 8 | date_reported DATE CHECK (EXTRACT(YEAR FROM date_reported) = 2010) 9 | ); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/create-tables.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs_2008 ( . . . ); 2 | CREATE TABLE Bugs_2009 ( . . . ); 3 | CREATE TABLE Bugs_2010 ( . . . ); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/data-integrity.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs_2009 2 | WHERE date_reported NOT BETWEEN '2009-01-01' AND '2009-12-31'; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/foreign-key.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | bug_id BIGINT UNSIGNED NOT NULL, 4 | FOREIGN KEY (bug_id) REFERENCES Bugs_????(bug_id) 5 | ); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/id-generator.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugsIdGenerator (bug_id SERIAL PRIMARY KEY); 2 | 3 | INSERT INTO BugsIdGenerator (bug_id) VALUES (DEFAULT); 4 | ROLLBACK; 5 | 6 | INSERT INTO Bugs_2010 (bug_id, . . .) 7 | VALUES (LAST_INSERT_ID(), . . .); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/insert.sql: -------------------------------------------------------------------------------- 1 | -- START:2010 2 | INSERT INTO Bugs_2010 (..., date_reported, ...) VALUES (..., '2010-06-01', ...); 3 | -- END:2010 4 | -- START:2011 5 | INSERT INTO Bugs_2011 (..., date_reported, ...) VALUES (..., '2011-02-20', ...); 6 | -- END:2011 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/join-union.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Accounts a 2 | JOIN ( 3 | SELECT * FROM Bugs_2008 4 | UNION ALL 5 | SELECT * FROM Bugs_2009 6 | UNION ALL 7 | SELECT * FROM Bugs_2010 8 | ) t ON (a.account_id = t.reported_by) 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/multi-column.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE ProjectHistory ( 2 | bugs_fixed_2008 INT, 3 | bugs_fixed_2009 INT, 4 | bugs_fixed_2010 INT 5 | ); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/synchronize.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Bugs_2009 (bug_id, date_reported, ...) 2 | SELECT bug_id, date_reported, ... 3 | FROM Bugs_2010 4 | WHERE bug_id = 1234; 5 | 6 | DELETE FROM Bugs_2010 WHERE bug_id = 1234; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/anti/union.sql: -------------------------------------------------------------------------------- 1 | SELECT b.status, COUNT(*) AS count_per_status FROM ( 2 | SELECT * FROM Bugs_2008 3 | UNION 4 | SELECT * FROM Bugs_2009 5 | UNION 6 | SELECT * FROM Bugs_2010 ) AS b 7 | GROUP BY b.status; 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/intro/alter-table.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Customers ADD (revenue2002 NUMBER(9,2)); 2 | ALTER TABLE Customers ADD (revenue2003 NUMBER(9,2)); 3 | ALTER TABLE Customers ADD (revenue2004 NUMBER(9,2)); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/intro/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Customers ( 2 | customer_id NUMBER(9) PRIMARY KEY, 3 | contact_info VARCHAR(255), 4 | business_type VARCHAR(20), 5 | revenue NUMBER(9,2) 6 | ); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/soln/create-history-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE ProjectHistory ( 2 | project_id BIGINT, 3 | year SMALLINT, 4 | bugs_fixed INT, 5 | PRIMARY KEY (project_id, year), 6 | FOREIGN KEY (project_id) REFERENCES Projects(project_id) 7 | ); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/soln/horiz-partition.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id SERIAL PRIMARY KEY, 3 | -- other columns 4 | date_reported DATE 5 | ) PARTITION BY HASH ( YEAR(date_reported) ) 6 | PARTITIONS 4; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/soln/separate-fixed-length.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id SERIAL PRIMARY KEY, -- fixed length data type 3 | summary CHAR(80), -- fixed length data type 4 | date_reported DATE, -- fixed length data type 5 | reported_by BIGINT UNSIGNED, -- fixed length data type 6 | FOREIGN KEY (reported_by) REFERENCES Accounts(account_id) 7 | ); 8 | 9 | CREATE TABLE BugDescriptions ( 10 | bug_id BIGINT UNSIGNED PRIMARY KEY, 11 | description VARCHAR(1000), -- variable length data type 12 | resolution VARCHAR(1000) -- variable length data type 13 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id) 14 | ); 15 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Metadata-Tribbles/soln/vert-partition.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE ProductInstallers ( 2 | product_id BIGINT UNSIGNED PRIMARY KEY, 3 | installer_image BLOB, 4 | FOREIGN KEY (product_id) REFERENCES Products(product_id) 5 | ); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/add-tag-two-step.sql: -------------------------------------------------------------------------------- 1 | -- START:select 2 | SELECT * FROM Bugs WHERE bug_id = 3456; 3 | -- END:select 4 | -- START:update 5 | UPDATE Bugs SET tag2 = 'performance' WHERE bug_id = 3456; 6 | -- END:update 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/add-tag.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs 2 | SET tag1 = CASE 3 | WHEN 'performance' IN (tag2, tag3) THEN tag1 4 | ELSE COALESCE(tag1, 'performance') END, 5 | tag2 = CASE 6 | WHEN 'performance' IN (tag1, tag3) THEN tag2 7 | ELSE COALESCE(tag2, 'performance') END, 8 | tag3 = CASE 9 | WHEN 'performance' IN (tag1, tag2) THEN tag3 10 | ELSE COALESCE(tag3, 'performance') END 11 | WHERE bug_id = 3456; 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/alter-table.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs ADD COLUMN tag4 VARCHAR(20); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id SERIAL PRIMARY KEY, 3 | description VARCHAR(1000), 4 | tag1 VARCHAR(20), 5 | tag2 VARCHAR(20), 6 | tag3 VARCHAR(20) 7 | ); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/insert-duplicate.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Bugs (description, tag1, tag2, tag3) 2 | VALUES ('printing is slow', 'printing', 'performance', 'performance'); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/remove-tag.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs 2 | SET tag1 = NULLIF(tag1, 'performance'), 3 | tag2 = NULLIF(tag2, 'performance'), 4 | tag3 = NULLIF(tag3, 'performance') 5 | WHERE bug_id = 3456; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/search-four-columns.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs 2 | WHERE tag1 = 'performance' 3 | OR tag2 = 'performance' 4 | OR tag3 = 'performance' 5 | OR tag4 = 'performance'; -- you must add this new term 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/search-two-tags.sql: -------------------------------------------------------------------------------- 1 | -- START:style1 2 | SELECT * FROM Bugs 3 | WHERE (tag1 = 'performance' OR tag2 = 'performance' OR tag3 = 'performance') 4 | AND (tag1 = 'printing' OR tag2 = 'printing' OR tag3 = 'printing'); 5 | -- END:style1 6 | -- START:style2 7 | SELECT * FROM Bugs 8 | WHERE 'performance' IN (tag1, tag2, tag3) 9 | AND 'printing' IN (tag1, tag2, tag3); 10 | -- END:style2 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/search.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs 2 | WHERE tag1 = 'performance' 3 | OR tag2 = 'performance' 4 | OR tag3 = 'performance'; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/anti/update.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs SET tag2 = 'performance' WHERE bug_id = 3456; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/soln/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Tags ( 2 | bug_id BIGINT UNSIGNED NOT NULL 3 | tag VARCHAR(20), 4 | PRIMARY KEY (bug_id, tag), 5 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id) 6 | ); 7 | 8 | INSERT INTO Tags (bug_id, tag) 9 | VALUES (1234, 'crash'), (3456, 'printing'), (3456, 'performance'); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/soln/insert-delete.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Tags (bug_id, tag) VALUES (1234, 'save'); 2 | 3 | DELETE FROM Tags WHERE bug_id = 1234 AND tag = 'crash'; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/soln/search-two-tags.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs 2 | JOIN Tags AS t1 USING (bug_id) 3 | JOIN Tags AS t2 USING (bug_id) 4 | WHERE t1.tag = 'printing' AND t2.tag = 'performance'; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Multi-Column/soln/search.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs JOIN Tags USING (bug_id) 2 | WHERE tag = 'performance'; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Neat-Freak/anti/lowest-value.sql: -------------------------------------------------------------------------------- 1 | SELECT b1.bug_id + 1 2 | FROM Bugs b1 3 | LEFT OUTER JOIN Bugs AS b2 ON (b1.bug_id + 1 = b2.bug_id) 4 | WHERE b2.bug_id IS NULL 5 | ORDER BY b1.bug_id LIMIT 1; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Neat-Freak/anti/renumber.sql: -------------------------------------------------------------------------------- 1 | UPDATE Bugs SET bug_id = 3 WHERE bug_id = 4; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Neat-Freak/soln/row_number.sql: -------------------------------------------------------------------------------- 1 | SELECT t1.* FROM 2 | (SELECT a.account_name, b.bug_id, b.summary, 3 | ROW_NUMBER() OVER (ORDER BY a.account_name, b.date_reported) AS rn 4 | FROM Accounts a JOIN Bugs b ON (a.account_id = b.reported_by)) AS t1 5 | WHERE t1.rn BETWEEN 51 AND 100; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Neat-Freak/soln/uniqueidentifier-sql2005.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id UNIQUEIDENTIFIER DEFAULT NEWID(), 3 | -- . . . 4 | ); 5 | 6 | INSERT INTO Bugs (bug_id, summary) 7 | VALUES (DEFAULT, 'crashes when I save'); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Normalization/2NF-anti.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugsTags ( 2 | bug_id BIGINT NOT NULL, 3 | tag VARCHAR(20) NOT NULL, 4 | tagger BIGINT NOT NULL, 5 | coiner BIGINT NOT NULL, 6 | PRIMARY KEY (bug_id, tag), 7 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 8 | FOREIGN KEY (tagger) REFERENCES Accounts(account_id), 9 | FOREIGN KEY (coiner) REFERENCES Accounts(account_id) 10 | ); 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Normalization/2NF-normal.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Tags ( 2 | tag VARCHAR(20) PRIMARY KEY, 3 | coiner BIGINT NOT NULL, 4 | FOREIGN KEY (coiner) REFERENCES Accounts(account_id) 5 | ); 6 | 7 | CREATE TABLE BugsTags ( 8 | bug_id BIGINT NOT NULL, 9 | tag VARCHAR(20) NOT NULL, 10 | tagger BIGINT NOT NULL, 11 | PRIMARY KEY (bug_id, tag), 12 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 13 | FOREIGN KEY (tag) REFERENCES Tags(tag), 14 | FOREIGN KEY (tagger) REFERENCES Accounts(account_id) 15 | ); 16 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Normalization/3NF-anti.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id SERIAL PRIMARY KEY 3 | -- . . . 4 | assigned_to BIGINT, 5 | assigned_email VARCHAR(100), 6 | FOREIGN KEY (assigned_to) REFERENCES Accounts(account_id) 7 | ); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Normalization/4NF-anti.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugsAccounts ( 2 | bug_id BIGINT NOT NULL, 3 | reported_by BIGINT, 4 | assigned_to BIGINT, 5 | verified_by BIGINT, 6 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 7 | FOREIGN KEY (reported_by) REFERENCES Accounts(account_id), 8 | FOREIGN KEY (assigned_to) REFERENCES Accounts(account_id), 9 | FOREIGN KEY (verified_by) REFERENCES Accounts(account_id) 10 | ); 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Normalization/5NF-anti.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugsAssigned ( 2 | bug_id BIGINT NOT NULL, 3 | assigned_to BIGINT NOT NULL, 4 | product_id BIGINT NOT NULL, 5 | PRIMARY KEY (bug_id, assigned_to), 6 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 7 | FOREIGN KEY (assigned_to) REFERENCES Accounts(account_id), 8 | FOREIGN KEY (product_id) REFERENCES Products(product_id) 9 | ); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Normalization/5NF-normal.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugsAssigned ( 2 | bug_id BIGINT NOT NULL, 3 | assigned_to BIGINT NOT NULL, 4 | PRIMARY KEY (bug_id, assigned_to), 5 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 6 | FOREIGN KEY (assigned_to) REFERENCES Accounts(account_id) 7 | ); 8 | CREATE TABLE EngineerProducts ( 9 | account_id BIGINT NOT NULL, 10 | product_id BIGINT NOT NULL, 11 | PRIMARY KEY (account_id, product_id), 12 | FOREIGN KEY (account_id) REFERENCES Accounts(account_id), 13 | FOREIGN KEY (product_id) REFERENCES Products(product_id) 14 | ); 15 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/anti/auth-lumping.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Accounts 2 | WHERE account_name = 'bill' AND password = 'opensesame'; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/anti/auth-plaintext.sql: -------------------------------------------------------------------------------- 1 | SELECT CASE WHEN password = 'opensesame' THEN 1 ELSE 0 END 2 | AS password_matches 3 | FROM Accounts 4 | WHERE account_id = 123; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/anti/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Accounts ( 2 | account_id SERIAL PRIMARY KEY, 3 | account_name VARCHAR(20) NOT NULL, 4 | email VARCHAR(100) NOT NULL, 5 | password VARCHAR(30) NOT NULL 6 | ); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/anti/insert-plaintext.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Accounts (account_id, account_name, email, password) 2 | VALUES (123, 'billkarwin', 'bill@example.com', 'xyzzy'); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/anti/select-plaintext.sql: -------------------------------------------------------------------------------- 1 | SELECT account_name, email, password 2 | FROM Accounts 3 | WHERE account_id = 123; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/soln/auth-hash.sql: -------------------------------------------------------------------------------- 1 | SELECT CASE WHEN password_hash = SHA2('xyzzy') THEN 1 ELSE 0 END 2 | AS password_matches 3 | FROM Accounts 4 | WHERE account_id = 123; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/soln/auth-salt.php: -------------------------------------------------------------------------------- 1 | query( 5 | "SELECT salt 6 | FROM Accounts 7 | WHERE account_name = 'bill'"); 8 | 9 | $row = $stmt->fetch(); 10 | $salt = $row[0]; 11 | 12 | $hash = hash('sha256', $password . $salt); 13 | 14 | $stmt = $pdo->query(" 15 | SELECT (password_hash = '$hash') AS password_matches; 16 | FROM Accounts AS a 17 | WHERE a.account_name = 'bill'"); 18 | 19 | $row = $stmt->fetch(); 20 | if ($row === false) { 21 | // account 'bill' does not exist 22 | } else { 23 | $password_matches = $row[0]; 24 | if (!$password_matches) { 25 | // password given was incorrect 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/soln/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Accounts ( 2 | account_id SERIAL PRIMARY KEY, 3 | account_name VARCHAR(20), 4 | email VARCHAR(100) NOT NULL, 5 | password_hash CHAR(64) NOT NULL 6 | ); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/soln/dictionary-attack.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE DictionaryHashes ( 2 | password VARCHAR(100), 3 | password_hash CHAR(64) 4 | ); 5 | 6 | SELECT a.account_name, h.password 7 | FROM Accounts AS a JOIN DictionaryHashes AS h 8 | ON a.password_hash = h.password_hash; 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/soln/insert-hash.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Accounts (account_id, account_name, email, password_hash) 2 | VALUES (123, 'billkarwin', 'bill@example.com', SHA2('xyzzy')); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/soln/reset-request.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE PasswordResetRequest ( 2 | token CHAR(32) PRIMARY KEY, 3 | account_id BIGINT UNSIGNED NOT NULL, 4 | expiration TIMESTAMP NOT NULL, 5 | FOREIGN KEY (account_id) REFERENCES Accounts(account_id) 6 | ); 7 | 8 | SET @token = MD5('billkarwin' || CURRENT_TIMESTAMP || RAND()); 9 | 10 | INSERT INTO PasswordResetRequest (token, account_id, expiration) 11 | VALUES (@token, 123, CURRENT_TIMESTAMP + INTERVAL 1 HOUR); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Passwords/soln/salt.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Accounts ( 2 | account_id SERIAL PRIMARY KEY, 3 | account_name VARCHAR(20), 4 | email VARCHAR(100) NOT NULL, 5 | password_hash CHAR(64) NOT NULL, 6 | salt BINARY(8) NOT NULL 7 | ); 8 | 9 | INSERT INTO Accounts (account_id, account_name, email, 10 | password_hash, salt) 11 | VALUES (123, 'billkarwin', 'bill@example.com', 12 | SHA2('xyzzy' || '-0xT!sp9'), '-0xT!sp9'); 13 | 14 | SELECT (password_hash = SHA2('xyzzy' || salt)) AS password_matches 15 | FROM Accounts 16 | WHERE account_id = 123; 17 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/anti/create-accounts.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Accounts ( 2 | account_id SERIAL PRIMARY KEY 3 | account_name VARCHAR(20), 4 | portrait_image BLOB 5 | ); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/anti/create-screenshots-path.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Screenshots ( 2 | bug_id BIGINT UNSIGNED NOT NULL, 3 | image_id BIGINT UNSIGNED NOT NULL, 4 | screenshot_path VARCHAR(100), 5 | caption VARCHAR(100), 6 | PRIMARY KEY (bug_id, image_id), 7 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id) 8 | ); 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/anti/create-screenshots.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Screenshots ( 2 | bug_id BIGINT UNSIGNED NOT NULL, 3 | image_id SERIAL NOT NULL, 4 | screenshot_image BLOB, 5 | caption VARCHAR(100), 6 | PRIMARY KEY (bug_id, image_id), 7 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id) 8 | ); 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/anti/delete.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM Screenshots WHERE bug_id = 1234 and image_id = 1; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/anti/file-get.php: -------------------------------------------------------------------------------- 1 | query("SELECT image_path FROM Screenshots 6 | WHERE bug_id = 1234 AND image_id = 1"); 7 | $row = $stmt->fetch(); 8 | $image_path = $row[0]; 9 | 10 | // Read the actual image -- I hope the path is correct! 11 | $image = file_get_contents(DATA_DIRECTORY . $image_path); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/anti/rollback.php: -------------------------------------------------------------------------------- 1 | query("DELETE FROM Screenshots 4 | WHERE bug_id = 1234 AND image_id =1"); 5 | 6 | unlink("images/screenshot1234-1.jpg"); 7 | 8 | $pdo->rollback(); 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/anti/transaction.php: -------------------------------------------------------------------------------- 1 | query("DELETE FROM Screenshots 4 | WHERE bug_id = 1234 AND image_id =1"); 5 | 6 | unlink('images/screenshot1234-1.jpg'); 7 | 8 | // Other clients still see the row in the database, 9 | // but not the image file. 10 | 11 | $pdo->commit(); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/soln/binary-content.php: -------------------------------------------------------------------------------- 1 | query("SELECT screenshot_image FROM Screenshots 6 | WHERE bug_id = 1234 AND image_id = 1"); 7 | $row = $stmt->fetch(); 8 | 9 | print $row[0]; 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/soln/create-screenshots.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Screenshots ( 2 | bug_id BIGINT UNSIGNED NOT NULL, 3 | image_id BIGINT UNSIGNED NOT NULL, 4 | screenshot_image BLOB, 5 | caption VARCHAR(100), 6 | PRIMARY KEY (bug_id, image_id), 7 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id) 8 | ); 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/soln/dumpfile.sql: -------------------------------------------------------------------------------- 1 | SELECT screenshot_image 2 | INTO DUMPFILE 'images/screenshot1234-1.jpg' 3 | FROM Screenshots 4 | WHERE bug_id = 1234 AND image_id =1; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Phantom-Files/soln/load-file.sql: -------------------------------------------------------------------------------- 1 | UPDATE Screenshots 2 | SET screenshot_image = LOAD_FILE('images/screenshot1234-1.jpg') 3 | WHERE bug_id = 1234 AND image_id = 1; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/anti/addresses.sql: -------------------------------------------------------------------------------- 1 | -- START:table 2 | CREATE TABLE Addresses ( 3 | address_id SERIAL PRIMARY KEY, 4 | parent VARCHAR(20), -- "Users" or "Orders" 5 | parent_id BIGINT UNSIGNED NOT NULL, 6 | address TEXT 7 | ); 8 | -- END:table 9 | -- START:weeds 10 | CREATE TABLE Addresses ( 11 | address_id SERIAL PRIMARY KEY, 12 | parent VARCHAR(20), -- "Users" or "Orders" 13 | parent_id BIGINT UNSIGNED NOT NULL, 14 | users_usage VARCHAR(20), -- "billing" or "shipping" 15 | orders_usage VARCHAR(20), -- "billing" or "shipping" 16 | address TEXT 17 | ); 18 | -- END:weeds 19 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/anti/comments.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | issue_type VARCHAR(20), -- "Bugs" or "FeatureRequests" 4 | issue_id BIGINT UNSIGNED NOT NULL, 5 | author BIGINT UNSIGNED NOT NULL, 6 | comment_date DATETIME, 7 | comment TEXT, 8 | FOREIGN KEY (author) REFERENCES Accounts(account_id) 9 | ); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/anti/select.sql: -------------------------------------------------------------------------------- 1 | -- START:issue 2 | SELECT * 3 | FROM Bugs AS b JOIN Comments AS c 4 | ON (b.issue_id = c.issue_id AND c.issue_type = 'Bugs') 5 | WHERE b.issue_id = 1234; 6 | -- END:issue 7 | -- START:comment 8 | SELECT * 9 | FROM Comments AS c 10 | LEFT OUTER JOIN Bugs AS b 11 | ON (b.issue_id = c.issue_id AND c.issue_type = 'Bugs') 12 | LEFT OUTER JOIN FeatureRequests AS f 13 | ON (f.issue_id = c.issue_id AND c.issue_type = 'FeatureRequests'); 14 | -- END:comment 15 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/intro/comments.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | bug_id BIGINT UNSIGNED NOT NULL, 4 | author_id BIGINT UNSIGNED NOT NULL, 5 | comment_date DATETIME NOT NULL, 6 | comment TEXT NOT NULL, 7 | FOREIGN KEY (author_id) REFERENCES Accounts(account_id), 8 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id) 9 | ); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/intro/nonsense.sql: -------------------------------------------------------------------------------- 1 | -- START:constraint 2 | ... 3 | FOREIGN KEY (issue_id) 4 | REFERENCES Bugs(issue_id) OR FeatureRequests(issue_id) 5 | ); 6 | -- END:constraint 7 | -- START:join 8 | SELECT c.*, i.summary, i.status 9 | FROM Comments AS c 10 | JOIN c.issue_type AS i USING (issue_id); 11 | -- END:join 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/recog/commentable.rb: -------------------------------------------------------------------------------- 1 | #--- 2 | # Excerpted from "SQL Antipatterns", 3 | # published by The Pragmatic Bookshelf. 4 | # Copyrights apply to this code. It may not be used to create training material, 5 | # courses, books, articles, and the like. Contact us if you are in doubt. 6 | # We make no guarantees that this code is fit for any purpose. 7 | # Visit http://www.pragmaticprogrammer.com/titles/bksqla for more book information. 8 | #--- 9 | class Comment < ActiveRecord::Base 10 | belongs_to :commentable, :polymorphic => true 11 | end 12 | 13 | class Bug < ActiveRecord::Base 14 | has_many :comments, :as => :commentable 15 | end 16 | 17 | class FeatureRequest < ActiveRecord::Base 18 | has_many :comments, :as => :commentable 19 | end 20 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/soln/reverse-coalesce.sql: -------------------------------------------------------------------------------- 1 | SELECT c.*, 2 | COALESCE(b.issue_id, f.issue_id ) AS issue_id, 3 | COALESCE(b.description, f.description) AS description, 4 | COALESCE(b.reporter, f.reporter ) AS reporter, 5 | COALESCE(b.priority, f.priority ) AS priority, 6 | COALESCE(b.status, f.status ) AS status, 7 | b.severity, 8 | b.version_affected, 9 | f.sponsor 10 | 11 | FROM Comments AS c 12 | LEFT OUTER JOIN (BugsComments JOIN Bugs AS b USING (issue_id)) 13 | USING (comment_id) 14 | LEFT OUTER JOIN (FeaturesComments JOIN FeatureRequests AS f USING (issue_id)) 15 | USING (comment_id) 16 | WHERE c.comment_id = 9876; 17 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/soln/reverse-join.sql: -------------------------------------------------------------------------------- 1 | -- START:issue 2 | SELECT * 3 | FROM BugsComments AS b 4 | JOIN Comments AS c USING (comment_id) 5 | WHERE b.issue_id = 1234; 6 | -- END:issue 7 | -- START:comment 8 | SELECT * 9 | FROM Comments AS c 10 | LEFT OUTER JOIN (BugsComments JOIN Bugs AS b USING (issue_id)) 11 | USING (comment_id) 12 | LEFT OUTER JOIN (FeaturesComments JOIN FeatureRequests AS f USING (issue_id)) 13 | USING (comment_id) 14 | WHERE c.comment_id = 9876; 15 | -- END:comment 16 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/soln/reverse-reference.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugsComments ( 2 | issue_id BIGINT UNSIGNED NOT NULL, 3 | comment_id BIGINT UNSIGNED NOT NULL, 4 | PRIMARY KEY (issue_id, comment_id), 5 | FOREIGN KEY (issue_id) REFERENCES Bugs(issue_id), 6 | FOREIGN KEY (comment_id) REFERENCES Comments(comment_id) 7 | ); 8 | 9 | 10 | CREATE TABLE FeaturesComments ( 11 | issue_id BIGINT UNSIGNED NOT NULL, 12 | comment_id BIGINT UNSIGNED NOT NULL, 13 | PRIMARY KEY (issue_id, comment_id), 14 | FOREIGN KEY (issue_id) REFERENCES FeatureRequests(issue_id), 15 | FOREIGN KEY (comment_id) REFERENCES Comments(comment_id) 16 | ); 17 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/soln/reverse-union.sql: -------------------------------------------------------------------------------- 1 | SELECT b.issue_id, b.description, b.reporter, b.priority, b.status, 2 | b.severity, b.version_affected, 3 | NULL AS sponsor 4 | FROM Comments AS c 5 | JOIN (BugsComments JOIN Bugs AS b USING (issue_id)) 6 | USING (comment_id) 7 | WHERE c.comment_id = 9876; 8 | 9 | UNION 10 | SELECT f.issue_id, f.description, f.reporter, f.priority, f.status, 11 | NULL AS severity, NULL AS version_affected, 12 | f.sponsor 13 | FROM Comments AS c 14 | JOIN (FeaturesComments JOIN FeatureRequests AS f USING (issue_id)) 15 | USING (comment_id) 16 | WHERE c.comment_id = 9876; 17 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/soln/reverse-unique.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE BugsComments ( 2 | issue_id BIGINT UNSIGNED NOT NULL, 3 | comment_id BIGINT UNSIGNED NOT NULL, 4 | UNIQUE KEY (comment_id), 5 | PRIMARY KEY (issue_id, comment_id), 6 | FOREIGN KEY (issue_id) REFERENCES Bugs(issue_id), 7 | FOREIGN KEY (comment_id) REFERENCES Comments(comment_id) 8 | ); 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Polymorphic/soln/super-join.sql: -------------------------------------------------------------------------------- 1 | -- START:comment 2 | SELECT * 3 | FROM Comments AS c 4 | LEFT OUTER JOIN Bugs AS b USING (issue_id) 5 | LEFT OUTER JOIN FeatureRequests AS f USING (issue_id) 6 | WHERE c.comment_id = 9876; 7 | -- END:comment 8 | -- START:issue 9 | SELECT * 10 | FROM Bugs AS b 11 | JOIN Comments AS c USING (issue_id) 12 | WHERE b.issue_id = 1234; 13 | -- END:issue 14 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/anti/indexed-sort.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs ORDER BY date_reported; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/anti/orderby-rand.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs ORDER BY RAND() LIMIT 1; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/soln/limit-offset.php: -------------------------------------------------------------------------------- 1 | query($rand)->fetch(PDO::FETCH_ASSOC); 4 | $sql = "SELECT * FROM Bugs LIMIT 1 OFFSET :offset"; 5 | $stmt = $pdo->prepare($sql); 6 | $stmt->execute( $offset ); 7 | $rand_bug = $stmt->fetch(); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/soln/next-higher.sql: -------------------------------------------------------------------------------- 1 | SELECT b1.* 2 | FROM Bugs AS b1 3 | JOIN (SELECT CEIL(RAND() * (SELECT MAX(bug_id) FROM Bugs)) AS bug_id) AS b2 4 | WHERE b1.bug_id >= b2.bug_id 5 | ORDER BY b1.bug_id 6 | LIMIT 1; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/soln/rand-1-to-max.sql: -------------------------------------------------------------------------------- 1 | SELECT b1.* 2 | FROM Bugs AS b1 3 | JOIN (SELECT CEIL(RAND() * (SELECT MAX(bug_id) FROM Bugs)) AS rand_id) AS b2 4 | ON (b1.bug_id = b2.rand_id); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/soln/rand-key-from-list.php: -------------------------------------------------------------------------------- 1 | query("SELECT bug_id FROM Bugs")->fetchAll(); 3 | 4 | $rand = random( count($bug_id_list) ); 5 | $rand_bug_id = $bug_id_list[$rand]["bug_id"]; 6 | 7 | $stmt = $pdo->prepare("SELECT * FROM Bugs WHERE bug_id = ?"); 8 | $stmt->execute( array($rand_bug_id) ); 9 | $rand_bug = $stmt->fetch(); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/soln/row_number.php: -------------------------------------------------------------------------------- 1 | query($rand)->fetch(PDO::FETCH_ASSOC); 5 | 6 | $sql = "WITH NumberedBugs AS ( 7 | SELECT b.*, ROW_NUMBER() OVER (ORDER BY bug_id) AS RN FROM Bugs b 8 | ) SELECT * FROM NumberedBugs WHERE RN = :offset"; 9 | $stmt = $pdo->prepare($sql); 10 | $stmt->execute( $offset ); 11 | $rand_bug = $stmt->fetch(); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/soln/sample-oracle.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM (SELECT * FROM Bugs SAMPLE (1) 2 | ORDER BY dbms_random.value) WHERE ROWNUM = 1; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Random/soln/tablesample-sql2005.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs TABLESAMPLE (1 ROWS); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/anti/cumulative.sql: -------------------------------------------------------------------------------- 1 | SELECT SUM( b.hours * a.hourly_rate ) AS project_cost 2 | FROM Bugs AS b 3 | JOIN Accounts AS a ON (b.assigned_to = a.account_id); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/anti/inexact.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Accounts WHERE hourly_rate = 59.95; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/anti/magnify-rate.sql: -------------------------------------------------------------------------------- 1 | SELECT hourly_rate * 1000000000 FROM Accounts WHERE account_id = 123; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/anti/select-rate.sql: -------------------------------------------------------------------------------- 1 | SELECT hourly_rate FROM Accounts WHERE account_id = 123; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/anti/threshold.sql: -------------------------------------------------------------------------------- 1 | -- START:coarse 2 | SELECT * FROM Accounts WHERE ABS(hourly_rate - 59.95) < 0.000001; 3 | -- END:coarse 4 | -- START:fine 5 | SELECT * FROM Accounts WHERE ABS(hourly_rate - 59.95) < 0.0000001; 6 | -- END:fine 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/intro/cost-per-bug.sql: -------------------------------------------------------------------------------- 1 | SELECT b.bug_id, b.hours * a.hourly_rate AS cost_per_bug 2 | FROM Bugs AS b 3 | JOIN Accounts AS a ON (b.assigned_to = a.account_id); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/intro/float-columns.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs ADD COLUMN hours FLOAT; 2 | 3 | ALTER TABLE Accounts ADD COLUMN hourly_rate FLOAT; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/soln/exact.sql: -------------------------------------------------------------------------------- 1 | SELECT hourly_rate FROM Accounts WHERE hourly_rate = 59.95; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/soln/magnify-rate-exact.sql: -------------------------------------------------------------------------------- 1 | SELECT hourly_rate * 1000000000 FROM Accounts WHERE hourly_rate = 59.95; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Rounding-Errors/soln/numeric-columns.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs ADD COLUMN hours NUMERIC(9,2); 2 | ALTER TABLE Accounts ADD COLUMN hourly_rate NUMERIC(9,2); -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/delete.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE bug_id = 1234; DELETE FROM Bugs 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/ohare-escape.php: -------------------------------------------------------------------------------- 1 | quote($_REQUEST["name"]); 3 | $sql = "SELECT * FROM Projects WHERE project_name = $project_name"; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/ohare-escape.sql: -------------------------------------------------------------------------------- 1 | -- START:standard 2 | SELECT * FROM Projects WHERE project_name = 'O''Hare' 3 | -- END:standard 4 | -- START:backslash 5 | SELECT * FROM Projects WHERE project_name = 'O\'Hare' 6 | -- END:backslash 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/ohare.php: -------------------------------------------------------------------------------- 1 | prepare("SELECT * FROM Projects WHERE project_name = ?"); 3 | $params = array($_REQUEST["name"]); 4 | $stmt->execute($params); 5 | ?> 6 | prepare("SELECT * FROM Bugs WHERE bug_id IN ( ? )"); 8 | $stmt->execute(array("1234,3456,5678")); 9 | ?> 10 | prepare("SELECT * FROM ? WHERE bug_id = 1234"); 12 | $stmt->execute(array("Bugs")); 13 | ?> 14 | prepare("SELECT * FROM Bugs ORDER BY ?"); 16 | $stmt->execute(array("date_reported")); 17 | ?> 18 | prepare("SELECT * FROM Bugs ORDER BY date_reported ?"); 20 | $stmt->execute(array("DESC")); 21 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/parameter.sql: -------------------------------------------------------------------------------- 1 | -- START:list 2 | SELECT * FROM Bugs WHERE bug_id IN ( '1234,3456,5678' ) 3 | -- END:list 4 | -- START:table 5 | SELECT * FROM 'Bugs' WHERE bug_id = 1234 6 | -- END:table 7 | -- START:column 8 | SELECT * FROM Bugs ORDER BY 'date_reported'; 9 | -- END:column 10 | -- START:keyword 11 | SELECT * FROM Bugs ORDER BY date_reported 'DESC' 12 | -- END:keyword 13 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/procedure.sql: -------------------------------------------------------------------------------- 1 | CREATE PROCEDURE UpdatePassword(input_password VARCHAR(20), 2 | input_userid VARCHAR(20)) 3 | BEGIN 4 | SET @sql = CONCAT('UPDATE Accounts 5 | SET password_hash = SHA2(', QUOTE(input_password), ') 6 | WHERE account_id = ', input_userid); 7 | PREPARE stmt FROM @sql; 8 | EXECUTE stmt; 9 | END 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/set-password-escape.php: -------------------------------------------------------------------------------- 1 | quote($_REQUEST["password"]); 3 | $userid = $pdo->quote($_REQUEST["userid"]); 4 | $sql = "UPDATE Accounts SET password_hash = SHA2($password) 5 | WHERE account_id = $userid"; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/set-password-escape.sql: -------------------------------------------------------------------------------- 1 | UPDATE Accounts SET password_hash = SHA2('xyzzy') 2 | WHERE account_id = '123 OR TRUE' 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/anti/set-password.php: -------------------------------------------------------------------------------- 1 | query($sql); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/casting.php: -------------------------------------------------------------------------------- 1 | query($sql); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/filter.php: -------------------------------------------------------------------------------- 1 | query($sql); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/interpolate.php: -------------------------------------------------------------------------------- 1 | quote($_REQUEST["active"]); 3 | $sql = "SELECT * FROM Accounts WHERE is_active = {$quoted_active}"; 4 | $stmt = $pdo->query($sql); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/mapping.php: -------------------------------------------------------------------------------- 1 | query($sql); 6 | 7 | $sortorders = array( "status" => "status", "date" => "date_reported" ); 8 | $directions = array( "up" => "ASC", "down" => "DESC" ); 9 | 10 | $sortorder = "bug_id"; 11 | $direction = "ASC"; 12 | 13 | if (array_key_exists($_REQUEST["order"], $sortorders)) { 14 | $sortorder = $sortorders[ $_REQUEST["order"] ]; 15 | } 16 | 17 | if (array_key_exists($_REQUEST["dir"], $directions)) { 18 | $direction = $directions[ $_REQUEST["dir"] ]; 19 | } 20 | 21 | $sql = "SELECT * FROM Bugs ORDER BY {$sortorder} {$direction}"; 22 | $stmt = $pdo->query($sql); 23 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/orderby.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs ORDER BY status ASC 2 | SELECT * FROM Bugs ORDER BY date_reported DESC 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/parameter-in.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 4 | $stmt->execute($bug_list); 5 | ?> 6 | prepare($sql); 10 | $stmt->execute($bug_list); 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/parameter.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 4 | $params = array($_REQUEST["password"], $_REQUEST["userid"]); 5 | $stmt->execute($params); 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/parameter.sql: -------------------------------------------------------------------------------- 1 | UPDATE Accounts SET password_hash = SHA2('xyzzy') 2 | WHERE account_id = '123 OR TRUE' 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/SQL-Injection/soln/regexp.php: -------------------------------------------------------------------------------- 1 | query($sql); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/anti/like-false-match.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE description LIKE '%one%'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/anti/like.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE description LIKE '%crash%'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/anti/regexp-word.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE description REGEXP '[[:<:]]one[[:>:]]'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/anti/regexp.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE description REGEXP 'crash'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/inverted-index/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Keywords ( 2 | keyword_id SERIAL PRIMARY KEY, 3 | keyword VARCHAR(40) NOT NULL, 4 | UNIQUE KEY (keyword) 5 | ); 6 | 7 | CREATE TABLE BugsKeywords ( 8 | keyword_id BIGINT UNSIGNED NOT NULL, 9 | bug_id BIGINT UNSIGNED NOT NULL, 10 | PRIMARY KEY (keyword_id, bug_id), 11 | FOREIGN KEY (keyword_id) REFERENCES Keywords(keyword_id), 12 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id) 13 | ); 14 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/inverted-index/trigger.sql: -------------------------------------------------------------------------------- 1 | DELIMITER // 2 | -- START:create 3 | CREATE TRIGGER Bugs_Insert AFTER INSERT ON Bugs 4 | FOR EACH ROW 5 | BEGIN 6 | INSERT INTO BugsKeywords (bug_id, keyword_id) 7 | SELECT NEW.bug_id, k.keyword_id FROM Keywords k 8 | WHERE NEW.description REGEXP CONCAT('[[:<:]]', k.keyword, '[[:>:]]') 9 | OR NEW.summary REGEXP CONCAT('[[:<:]]', k.keyword, '[[:>:]]'); 10 | END 11 | -- END:create 12 | // 13 | DELIMITER ; 14 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/lucene/create-index.php: -------------------------------------------------------------------------------- 1 | query("SELECT bug_id, summary, description FROM Bugs"); 5 | 6 | while ($row = $stmt->fetch()) { 7 | $doc = new Zend_Search_Lucene_Document(); 8 | $doc->addField(Zend_Search_Lucene_Field::UnIndexed("bug_id", 9 | $row["bug_id"])); 10 | $doc->addField(Zend_Search_Lucene_Field::Text("summary", 11 | $row["summary"])); 12 | $doc->addField(Zend_Search_Lucene_Field::Text("description", 13 | $row["description"])); 14 | $index->addDocument($doc); 15 | } 16 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/lucene/search.php: -------------------------------------------------------------------------------- 1 | find($search_expr); 7 | 8 | $bug_id_list = array("0"); 9 | foreach ($matches as $match) { 10 | $bug_id_list[] = intval($match->bug_id); 11 | } 12 | $bug_id_list = join(",", $bug_id_list); 13 | 14 | $stmt = $pdo->query("SELECT * FROM Bugs WHERE bug_id IN ($bug_id_list)"); 15 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/microsoft/catalog.sql: -------------------------------------------------------------------------------- 1 | EXEC sp_fulltext_database 'enable' 2 | EXEC sp_fulltext_catalog 'BugsCatalog', 'create' 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/microsoft/create-index.sql: -------------------------------------------------------------------------------- 1 | EXEC sp_fulltext_table 'Bugs', 'create', 'BugsCatalog', 'bug_id' 2 | EXEC sp_fulltext_column 'Bugs', 'summary', 'add', '2057' 3 | EXEC sp_fulltext_column 'Bugs', 'description', 'add', '2057' 4 | EXEC sp_fulltext_table 'Bugs', 'activate' 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/microsoft/search.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE CONTAINS(summary, '"crash"'); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/microsoft/start.sql: -------------------------------------------------------------------------------- 1 | EXEC sp_fulltext_table 'Bugs', 'start_change_tracking' 2 | EXEC sp_fulltext_table 'Bugs', 'start_background_updateindex' 3 | EXEC sp_fulltext_table 'Bugs', 'start_full' 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/mysql/alter-table.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE Bugs ADD FULLTEXT INDEX bugfts (summary, description); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/mysql/match-boolean.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE MATCH(summary, description) 2 | AGAINST ('+crash -save' IN BOOLEAN MODE); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/mysql/match.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE MATCH(summary, description) AGAINST ('crash'); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/oracle/create-index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX BugsText ON Bugs(summary) INDEXTYPE IS CTXSYS.CONTEXT; 2 | 3 | SELECT * FROM Bugs WHERE CONTAINS(summary, 'crash') > 0; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/oracle/ctxcat-create.sql: -------------------------------------------------------------------------------- 1 | CTX_DDL.CREATE_INDEX_SET('BugsCatalogSet'); 2 | CTX_DDL.ADD_INDEX('BugsCatalogSet', 'status'); 3 | CTX_DDL.ADD_INDEX('BugsCatalogSet', 'priority'); 4 | 5 | CREATE INDEX BugsCatalog ON Bugs(summary) INDEXTYPE IS CTXSYS.CTXCAT 6 | PARAMETERS('BugsCatalogSet'); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/oracle/ctxcat-search.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs 2 | WHERE CATSEARCH(summary, '(crash save)', 'status = "NEW"') > 0; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/oracle/ctxxpath.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX BugTestXml ON Bugs(testoutput) INDEXTYPE IS CTXSYS.CTXXPATH; 2 | 3 | SELECT * FROM Bugs 4 | WHERE testoutput.existsNode('/testsuite/test[@status="fail"]') > 0; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/postgresql/create-index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX bugs_ts ON Bugs USING GIN(ts_bugtext); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/postgresql/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Bugs ( 2 | bug_id SERIAL PRIMARY KEY, 3 | summary VARCHAR(80), 4 | description TEXT, 5 | ts_bugtext TSVECTOR 6 | -- other columns 7 | ); 8 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/postgresql/search.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Bugs WHERE ts_bugtext @@ to_tsquery('crash'); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/postgresql/trigger.sql: -------------------------------------------------------------------------------- 1 | CREATE TRIGGER ts_bugtext BEFORE INSERT OR UPDATE ON Bugs 2 | FOR EACH ROW EXECUTE PROCEDURE 3 | tsvector_update_trigger(ts_bugtext, 'pg_catalog.english', summary, description); 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sphinx/indexer.sh: -------------------------------------------------------------------------------- 1 | #--- 2 | # Excerpted from "SQL Antipatterns", 3 | # published by The Pragmatic Bookshelf. 4 | # Copyrights apply to this code. It may not be used to create training material, 5 | # courses, books, articles, and the like. Contact us if you are in doubt. 6 | # We make no guarantees that this code is fit for any purpose. 7 | # Visit http://www.pragmaticprogrammer.com/titles/bksqla for more book information. 8 | #--- 9 | indexer -c sphinx.conf bugs 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sphinx/search.sh: -------------------------------------------------------------------------------- 1 | #--- 2 | # Excerpted from "SQL Antipatterns", 3 | # published by The Pragmatic Bookshelf. 4 | # Copyrights apply to this code. It may not be used to create training material, 5 | # courses, books, articles, and the like. Contact us if you are in doubt. 6 | # We make no guarantees that this code is fit for any purpose. 7 | # Visit http://www.pragmaticprogrammer.com/titles/bksqla for more book information. 8 | #--- 9 | search -b "crash -save" 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sphinx/sphinx.conf: -------------------------------------------------------------------------------- 1 | source bugsrc 2 | { 3 | type = mysql 4 | sql_user = bugsuser 5 | sql_pass = xyzzy 6 | sql_db = bugsdatabase 7 | sql_query = \ 8 | SELECT bug_id, status, date_reported, summary, description \ 9 | FROM Bugs 10 | sql_attr_timestamp = date_reported 11 | sql_attr_str2ordinal = status 12 | sql_query_info = SELECT * FROM Bugs WHERE bug_id = $id 13 | } 14 | 15 | index bugs 16 | { 17 | source = bugsrc 18 | path = /opt/local/var/db/sphinx/bugs 19 | } 20 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sqlite/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE BugsText USING fts3(summary, description); 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sqlite/insert.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO BugsText (docid, summary, description) 2 | SELECT bug_id, summary, description FROM Bugs; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sqlite/makefile.in: -------------------------------------------------------------------------------- 1 | TCC += -DSQLITE_CORE=1 2 | TCC += -DSQLITE_ENABLE_FTS3=1 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sqlite/search-boolean.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM BugsText WHERE BugsText MATCH 'crash -save'; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Search/soln/sqlite/search.sql: -------------------------------------------------------------------------------- 1 | SELECT b.* FROM BugsText t JOIN Bugs b ON (t.docid = b.bug_id) 2 | WHERE BugsText MATCH 'crash'; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/See-No-Evil/anti/no-check.php: -------------------------------------------------------------------------------- 1 | prepare($sql); //(2) 7 | $stmt->execute(array(1, "OPEN")); //(3) 8 | $bug = $stmt->fetch(); //(4) 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/See-No-Evil/anti/white-space.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/See-No-Evil/anti/white-space.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM BugsWHERE bug_id = 1234 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/anti/cartesian-no-group.sql: -------------------------------------------------------------------------------- 1 | SELECT p.product_id, f.bug_id AS fixed, o.bug_id AS open 2 | FROM BugsProducts p 3 | JOIN Bugs f ON (p.bug_id = f.bug_id AND f.status = 'FIXED') 4 | JOIN BugsProducts p2 USING (product_id) 5 | JOIN Bugs o ON (p2.bug_id = o.bug_id AND o.status = 'OPEN') 6 | WHERE p.product_id = 1; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/anti/cartesian.sql: -------------------------------------------------------------------------------- 1 | SELECT p.product_id, 2 | COUNT(f.bug_id) AS count_fixed, 3 | COUNT(o.bug_id) AS count_open 4 | FROM BugsProducts p 5 | LEFT OUTER JOIN (BugsProducts bpf JOIN Bugs f USING (bug_id)) f 6 | ON (p.bug_id = f.bug_id AND f.status = 'FIXED') 7 | LEFT OUTER JOIN (BugsProducts bpo JOIN Bugs o USING (bug_id)) o 8 | ON (p.bug_id = o.bug_id AND o.status = 'OPEN') 9 | WHERE p.product_id = 1 10 | GROUP BY p.product_id; 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/intro/report.sql: -------------------------------------------------------------------------------- 1 | SELECT COUNT(bp.product_id) AS how_many_products, 2 | COUNT(dev.account_id) AS how_many_developers, 3 | COUNT(b.bug_id)/COUNT(dev.account_id) AS avg_bugs_per_developer, 4 | COUNT(cust.account_id) AS how_many_customers 5 | FROM Bugs b JOIN BugsProducts bp ON (b.bug_id = bp.bug_id) 6 | JOIN Accounts dev ON (b.assigned_to = dev.account_id) 7 | JOIN Accounts cust ON (b.reported_by = cust.account_id) 8 | WHERE cust.email NOT LIKE '%@example.com' 9 | GROUP BY bp.product_id; 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/soln/bugs-by-customers.sql: -------------------------------------------------------------------------------- 1 | SELECT COUNT(*) AS how_many_customer_bugs 2 | FROM Bugs b JOIN Accounts cust ON (b.reported_by = cust.account_id) 3 | WHERE b.status = 'FIXED' AND cust.email NOT LIKE '%@example.com'; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/soln/bugs-per-developer.sql: -------------------------------------------------------------------------------- 1 | SELECT AVG(bugs_per_developer) AS average_bugs_per_developer 2 | FROM (SELECT dev.account_id, COUNT(*) AS bugs_per_developer 3 | FROM Bugs b JOIN Accounts dev 4 | ON (b.assigned_to = dev.account_id) 5 | WHERE b.status = 'FIXED' 6 | GROUP BY dev.account_id) t; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/soln/count-developers.sql: -------------------------------------------------------------------------------- 1 | SELECT COUNT(DISTINCT assigned_to) AS how_many_developers 2 | FROM Bugs 3 | WHERE status = 'FIXED'; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/soln/count-products.sql: -------------------------------------------------------------------------------- 1 | SELECT COUNT(*) AS how_many_products 2 | FROM Products; 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/soln/generate-update.sql: -------------------------------------------------------------------------------- 1 | SELECT CONCAT('UPDATE Inventory ' 2 | ' SET last_used = ''', MAX(u.usage_date), '''', 3 | ' WHERE inventory_id = ', u.inventory_id, ';') AS update_statement 4 | FROM ComputerUsage u 5 | GROUP BY u.inventory_id; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/soln/split-query.sql: -------------------------------------------------------------------------------- 1 | SELECT p.product_id, COUNT(f.bug_id) AS count_fixed 2 | FROM BugsProducts p 3 | LEFT OUTER JOIN Bugs f ON (p.bug_id = f.bug_id AND f.status = 'FIXED') 4 | WHERE p.product_id = 1 5 | GROUP BY p.product_id; 6 | 7 | SELECT p.product_id, COUNT(o.bug_id) AS count_open 8 | FROM BugsProducts p 9 | LEFT OUTER JOIN Bugs o ON (p.bug_id = o.bug_id AND o.status = 'OPEN') 10 | WHERE p.product_id = 1 11 | GROUP BY p.product_id; 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Spaghetti-Query/soln/union.sql: -------------------------------------------------------------------------------- 1 | (SELECT p.product_id, f.status, COUNT(f.bug_id) AS bug_count 2 | FROM BugsProducts p 3 | LEFT OUTER JOIN Bugs f ON (p.bug_id = f.bug_id AND f.status = 'FIXED') 4 | WHERE p.product_id = 1 5 | GROUP BY p.product_id, f.status) 6 | 7 | UNION ALL 8 | 9 | (SELECT p.product_id, o.status, COUNT(o.bug_id) AS bug_count 10 | FROM BugsProducts p 11 | LEFT OUTER JOIN Bugs o ON (p.bug_id = o.bug_id AND o.status = 'OPEN') 12 | WHERE p.product_id = 1 13 | GROUP BY p.product_id, o.status) 14 | 15 | ORDER BY bug_count; 16 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/adjacency-list.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | parent_id BIGINT UNSIGNED, 4 | bug_id BIGINT UNSIGNED NOT NULL, 5 | author BIGINT UNSIGNED NOT NULL, 6 | comment_date DATETIME NOT NULL, 7 | comment TEXT NOT NULL, 8 | FOREIGN KEY (parent_id) REFERENCES Comments(comment_id), 9 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 10 | FOREIGN KEY (author) REFERENCES Accounts(account_id) 11 | ); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/all-comments.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Comments WHERE bug_id = 1234; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/ancestors.sql: -------------------------------------------------------------------------------- 1 | SELECT c1.*, c2.*, c3.*, c4.* 2 | FROM Comments c1 -- 1st level 3 | LEFT OUTER JOIN Comments c2 4 | ON c2.parent_id = c1.comment_id -- 2nd level 5 | LEFT OUTER JOIN Comments c3 6 | ON c3.parent_id = c2.comment_id -- 3rd level 7 | LEFT OUTER JOIN Comments c4 8 | ON c4.parent_id = c3.comment_id; -- 4th level 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/delete-non-leaf.sql: -------------------------------------------------------------------------------- 1 | SELECT parent_id FROM Comments WHERE comment_id = 6; -- returns 4 2 | UPDATE Comments SET parent_id = 4 WHERE parent_id = 6; 3 | DELETE FROM Comments WHERE comment_id = 6; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/delete-subtree.sql: -------------------------------------------------------------------------------- 1 | SELECT comment_id FROM Comments WHERE parent_id = 4; -- returns 5 and 6 2 | SELECT comment_id FROM Comments WHERE parent_id = 5; -- returns none 3 | SELECT comment_id FROM Comments WHERE parent_id = 6; -- returns 7 4 | SELECT comment_id FROM Comments WHERE parent_id = 7; -- returns none 5 | 6 | DELETE FROM Comments WHERE comment_id IN ( 7 ); 7 | DELETE FROM Comments WHERE comment_id IN ( 5, 6 ); 8 | DELETE FROM Comments WHERE comment_id = 4; 9 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/insert.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Comments (bug_id, parent_id, author, comment) 2 | VALUES (1234, 7, 'Kukla', 'Thanks!'); 3 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/parent.sql: -------------------------------------------------------------------------------- 1 | SELECT c1.*, c2.* 2 | FROM Comments c1 LEFT OUTER JOIN Comments c2 3 | ON c2.parent_id = c1.comment_id; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/anti/update.sql: -------------------------------------------------------------------------------- 1 | UPDATE Comments SET parent_id = 3 WHERE comment_id = 6; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/intro/parent.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | parent_id BIGINT UNSIGNED, 4 | comment TEXT NOT NULL, 5 | FOREIGN KEY (parent_id) REFERENCES Comments(comment_id) 6 | ); 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/legit/connect-by.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM Comments 2 | START WITH comment_id = 9876 3 | CONNECT BY PRIOR parent_id = comment_id; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/legit/cte.sql: -------------------------------------------------------------------------------- 1 | WITH CommentTree 2 | (comment_id, bug_id, parent_id, author, comment, depth) 3 | AS ( 4 | SELECT *, 0 AS depth FROM Comments 5 | WHERE parent_id IS NULL 6 | UNION ALL 7 | SELECT c.*, ct.depth+1 AS depth FROM CommentTree ct 8 | JOIN Comments c ON (ct.comment_id = c.parent_id) 9 | ) 10 | SELECT * FROM CommentTree WHERE bug_id = 1234; 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/ancestors.sql: -------------------------------------------------------------------------------- 1 | SELECT c.* 2 | FROM Comments AS c 3 | JOIN TreePaths AS t ON c.comment_id = t.ancestor 4 | WHERE t.descendant = 6; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/child.sql: -------------------------------------------------------------------------------- 1 | SELECT * 2 | FROM TreePaths 3 | WHERE ancestor = 4 AND path_length = 1; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | bug_id BIGINT UNSIGNED NOT NULL, 4 | author BIGINT UNSIGNED NOT NULL, 5 | comment_date DATETIME NOT NULL, 6 | comment TEXT NOT NULL, 7 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 8 | FOREIGN KEY (author) REFERENCES Accounts(account_id) 9 | ); 10 | 11 | CREATE TABLE TreePaths ( 12 | ancestor BIGINT UNSIGNED NOT NULL, 13 | descendant BIGINT UNSIGNED NOT NULL, 14 | PRIMARY KEY(ancestor, descendant), 15 | FOREIGN KEY (ancestor) REFERENCES Comments(comment_id), 16 | FOREIGN KEY (descendant) REFERENCES Comments(comment_id) 17 | ); 18 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/delete-leaf.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM TreePaths WHERE descendant = 7; 2 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/delete-subtree.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM TreePaths 2 | WHERE descendant IN (SELECT descendant 3 | FROM TreePaths 4 | WHERE ancestor = 4); 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/descendants.sql: -------------------------------------------------------------------------------- 1 | SELECT c.* 2 | FROM Comments AS c 3 | JOIN TreePaths AS t ON c.comment_id = t.descendant 4 | WHERE t.ancestor = 4; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/insert.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO TreePaths (ancestor, descendant) 2 | SELECT t.ancestor, 8 3 | FROM TreePaths AS t 4 | WHERE t.descendant = 5 5 | UNION ALL 6 | SELECT 8, 8; 7 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/closure-table/move-subtree.sql: -------------------------------------------------------------------------------- 1 | -- START:delete 2 | DELETE FROM TreePaths 3 | WHERE descendant IN (SELECT descendant 4 | FROM TreePaths 5 | WHERE ancestor = 6) 6 | AND ancestor IN (SELECT ancestor 7 | FROM TreePaths 8 | WHERE descendant = 6 9 | AND ancestor != descendant); 10 | -- END:delete 11 | -- START:reinsert 12 | INSERT INTO TreePaths (ancestor, descendant) 13 | SELECT supertree.ancestor, subtree.descendant 14 | FROM TreePaths AS supertree 15 | CROSS JOIN TreePaths AS subtree 16 | WHERE supertree.descendant = 3 17 | AND subtree.ancestor = 6; 18 | -- END:reinsert 19 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/nested-sets/ancestors.sql: -------------------------------------------------------------------------------- 1 | SELECT c2.* 2 | FROM Comments AS c1 3 | JOIN Comment AS c2 4 | ON c1.nsleft BETWEEN c2.nsleft AND c2.nsright 5 | WHERE c1.comment_id = 6; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/nested-sets/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | nsleft INTEGER NOT NULL, 4 | nsright INTEGER NOT NULL, 5 | bug_id BIGINT UNSIGNED NOT NULL, 6 | author BIGINT UNSIGNED NOT NULL, 7 | comment_date DATETIME NOT NULL, 8 | comment TEXT NOT NULL, 9 | FOREIGN KEY (bug_id) REFERENCES Bugs (bug_id), 10 | FOREIGN KEY (author) REFERENCES Accounts(account_id) 11 | ); 12 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/nested-sets/depth.sql: -------------------------------------------------------------------------------- 1 | -- Reports depth = 3 2 | SELECT c1.comment_id, COUNT(c2.comment_id) AS depth 3 | FROM Comment AS c1 4 | JOIN Comment AS c2 5 | ON c1.nsleft BETWEEN c2.nsleft AND c2.nsright 6 | WHERE c1.comment_id = 7 7 | GROUP BY c1.comment_id; 8 | 9 | DELETE FROM Comment WHERE comment_id = 6; 10 | 11 | -- Reports depth = 2 12 | SELECT c1.comment_id, COUNT(c2.comment_id) AS depth 13 | FROM Comment AS c1 14 | JOIN Comment AS c2 15 | ON c1.nsleft BETWEEN c2.nsleft AND c2.nsright 16 | WHERE c1.comment_id = 7 17 | GROUP BY c1.comment_id; 18 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/nested-sets/descendants.sql: -------------------------------------------------------------------------------- 1 | SELECT c2.* 2 | FROM Comments AS c1 3 | JOIN Comments as c2 4 | ON c2.nsleft BETWEEN c1.nsleft AND c1.nsright 5 | WHERE c1.comment_id = 4; 6 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/nested-sets/insert.sql: -------------------------------------------------------------------------------- 1 | -- make space for NS values 8 and 9 2 | UPDATE Comment 3 | SET nsleft = CASE WHEN nsleft >= 8 THEN nsleft+2 ELSE nsleft END, 4 | nsright = nsright+2 5 | WHERE nsright >= 7; 6 | 7 | -- create new child of comment #5, occupying NS values 8 and 9 8 | INSERT INTO Comment (nsleft, nsright, author, comment) 9 | VALUES (8, 9, 'Fran', 'Me too!'); 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/nested-sets/parent.sql: -------------------------------------------------------------------------------- 1 | SELECT parent.* 2 | FROM Comment AS c 3 | JOIN Comment AS parent 4 | ON c.nsleft BETWEEN parent.nsleft AND parent.nsright 5 | LEFT OUTER JOIN Comment AS in_between 6 | ON c.nsleft BETWEEN in_between.nsleft AND in_between.nsright 7 | AND in_between.nsleft BETWEEN parent.nsleft AND parent.nsright 8 | WHERE c.comment_id = 6 9 | AND in_between.comment_id IS NULL; 10 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/path-enum/ancestors.sql: -------------------------------------------------------------------------------- 1 | SELECT * 2 | FROM Comments AS c 3 | WHERE '1/4/6/7/' LIKE c.path || '%'; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/path-enum/count.sql: -------------------------------------------------------------------------------- 1 | SELECT COUNT(*) 2 | FROM Comments AS c 3 | WHERE c.path LIKE '1/4/' || '%' 4 | GROUP BY c.author; 5 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/path-enum/create-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE Comments ( 2 | comment_id SERIAL PRIMARY KEY, 3 | path VARCHAR(1000), 4 | bug_id BIGINT UNSIGNED NOT NULL, 5 | author BIGINT UNSIGNED NOT NULL, 6 | comment_date DATETIME NOT NULL, 7 | comment TEXT NOT NULL, 8 | FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), 9 | FOREIGN KEY (author) REFERENCES Accounts(account_id) 10 | ); 11 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/path-enum/descendants.sql: -------------------------------------------------------------------------------- 1 | SELECT * 2 | FROM Comments AS c 3 | WHERE c.path LIKE '1/4/' || '%'; 4 | -------------------------------------------------------------------------------- /SQL AntiPatterns/code/Trees/soln/path-enum/insert.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Comments (author, comment) VALUES ('Ollie', 'Good job!'); 2 | UPDATE Comments 3 | SET path = (SELECT path FROM Comments WHERE comment_id = 7) 4 | || LAST_INSERT_ID() || '/' 5 | WHERE comment_id = LAST_INSERT_ID(); 6 | -------------------------------------------------------------------------------- /Test-Driven-Development/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | test { 13 | useJUnitPlatform() 14 | } 15 | 16 | dependencies { 17 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' 18 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' 19 | } 20 | -------------------------------------------------------------------------------- /Test-Driven-Development/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/Test-Driven-Development/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Test-Driven-Development/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /Test-Driven-Development/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Test-Driven-Development' 2 | 3 | -------------------------------------------------------------------------------- /Test-Driven-Development/src/test/java/Hello.java: -------------------------------------------------------------------------------- 1 | import org.junit.jupiter.api.Test; 2 | 3 | public class Hello { 4 | 5 | @Test 6 | void hello() { 7 | System.out.println("Hello World"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /UML실전에서는이것만쓴다/template.md: -------------------------------------------------------------------------------- 1 | # UML 실전에서는 이것만 쓴다 - JAVA 프로그래머를 위한 UML 2 | 3 | ## {n} chapter 주제 4 | 5 | 해당 글은 Robert C.Martin 'UML 실전에서는 이것만 쓴다' 라는 책을 읽고 학습한 내용을 정리 및 회고하는 글 입니다. 6 | 7 | UML 실전에서는 이것만 쓴다 - JAVA 프로그래머를 위한 UML 8 | 인사이트 출판사 9 | 지은이: Robert C.Martin (Uncle Bob) 10 | 옮긴이: 이용원, 정지호 11 | 12 |
13 | pic 14 |
15 | 16 | ### 이번 장에서 이야기하고자 하는 것 17 | 18 | ### 나의 해석과 회고 19 | -------------------------------------------------------------------------------- /Working Effectively with Legacy Code/CH17_내 애플리케이션은 뼈대가 약하다.md: -------------------------------------------------------------------------------- 1 | # CHAPTER 17 내 애플리케이션은 뼈대가 약하다 2 | 3 | 4 | 5 | ## 배경 6 | 7 | 오래된 어플리케이션 일 경우 무질서하게 확장되기 쉽다. 8 | 9 | 개발 팀이 아키텍처를 이해하고 있지 않다면 아키텍처는 계속 퇴보한다. 그 이유는? 10 | 11 | - 시스템이 너무 복잡해서 전체 그림을 이해하는 데 오랜 시간이 걸린다 12 | - 시스템이 너무 복잡해서 전체 그림이 아예 없다 13 | - 전체 그림이 없다 보니 긴급 상황이 끊임없이 발생한다. 그리고 이를 처리하느라 땜질 처방에 급급하게 된다. 14 | 15 | 16 | 17 | 여러 기법을 수행해서 팀원들이 아키텍처에 관한 관심을 유지하는 데 도움이 되고, 아키텍쳐를 유지하기 위해 가장 중요한 것이다. 자주 관심을 기울이지 않는 것은 잊혀지기 쉽다. 18 | 19 | 20 | 21 | ## 시스템의 스토리 텔링 22 | 23 | 2명이 서로 질문한다 24 | 25 | "시스템의 아키턱처는 어떤가요?" 그러면 상대방은 최대 2~3개만의 개념을 갖고 시스템의 아키텍쳐를 설명하려고 노력한다. 26 | 27 | - 팀 차원의 의견 공유를 목적으로 시스템의 스토리를 자주 이야기하도록 격려하자. 28 | 29 | -------------------------------------------------------------------------------- /Working Effectively with Legacy Code/CH18_테스트 코드가 방해를 한다.md: -------------------------------------------------------------------------------- 1 | # 테스트 코드가 방해를 한다 2 | 3 | 어떻게 하면 테스트 코드가 방해가 될 수 있을까? 프로덕트 코드를 검증하기 위해 테스트 코드를 작성하곤 한다. 하지만 무엇을 테스트할 것인지 모른다면 그다지 도움이 될 수 없다. 4 | 5 | 6 | 7 | 어떤 식으로든 규칙을 정해 작업하지 않으면 테스트 코드의 바다에 빠지게 될 것이다. 8 | 9 | 10 | 11 | ### 클래스 명명 규칙 12 | 13 | - 일반적으로 각 클래스마다 적어도 한 개의 단위 테스트 클래스를 작성한다. 따라서 테스트 대상 클래스의 이름을 바탕으로 단위 테스트 클래스를 만드는 것이 합리적이다. 14 | - 보편적으로 클래스 이름의 접두어나 접미어로서 Test 을 붙이는 것 15 | 16 | ### 테스트 코드의 배치 17 | 18 | - src / test 디렉토리 나누기 -------------------------------------------------------------------------------- /Working Effectively with Legacy Code/CH22-괴물메서드를 변경해야하는데 테스트 코드를 작성하지 못하겠다.md: -------------------------------------------------------------------------------- 1 | # CH22. '괴물 메서드'를 변경해야 하는데 테스트 코드를 작성하지 못하겠다 2 | 3 | 4 | 5 | 괴물 메소드를 만나면 어떻게 테스트 코드를 작성할 수 있을까? 6 | 7 | 그 전에 괴물 메소드는 다음과 같은 형태가 있다. 8 | 9 | - 불릿 메소드 10 | 11 | 들여쓰기가 거의 돼 있지 않은 메소드를 말한다. 단지 글머리 기호(블릿)를 갖는 코드 덩어리의 목록을 연상시키기 위해 이렇게 -------------------------------------------------------------------------------- /YOU-DON'T-KNOW-JS/Type-Grammer/REFEREANCE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [자바스크립트의 스코프와 클로저 : TOAST Meetup ](http://meetup.toast.com/posts/86) 4 | 5 | [함수의 범위(scope)](https://www.zerocho.com/category/JavaScript/post/5740531574288ebc5f2ba97e) -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker -------------------------------------------------------------------------------- /asset/image-20241025073215384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025073215384.png -------------------------------------------------------------------------------- /asset/image-20241025075102856.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025075102856.png -------------------------------------------------------------------------------- /asset/image-20241025075216018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025075216018.png -------------------------------------------------------------------------------- /asset/image-20241025075553244.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025075553244.png -------------------------------------------------------------------------------- /asset/image-20241025080510228.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025080510228.png -------------------------------------------------------------------------------- /asset/image-20241025080520927.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025080520927.png -------------------------------------------------------------------------------- /asset/image-20241025081144309.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025081144309.png -------------------------------------------------------------------------------- /asset/image-20241025081233681.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025081233681.png -------------------------------------------------------------------------------- /asset/image-20241025081505978.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025081505978.png -------------------------------------------------------------------------------- /asset/image-20241025082538446.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025082538446.png -------------------------------------------------------------------------------- /asset/image-20241025082627905.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025082627905.png -------------------------------------------------------------------------------- /asset/image-20241025083659761.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025083659761.png -------------------------------------------------------------------------------- /asset/image-20241025090159987.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241025090159987.png -------------------------------------------------------------------------------- /asset/image-20241026000546986.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026000546986.png -------------------------------------------------------------------------------- /asset/image-20241026000800907.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026000800907.png -------------------------------------------------------------------------------- /asset/image-20241026001531720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026001531720.png -------------------------------------------------------------------------------- /asset/image-20241026001947693.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026001947693.png -------------------------------------------------------------------------------- /asset/image-20241026004238474.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026004238474.png -------------------------------------------------------------------------------- /asset/image-20241026004959185.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026004959185.png -------------------------------------------------------------------------------- /asset/image-20241026092259964.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026092259964.png -------------------------------------------------------------------------------- /asset/image-20241026092347651.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026092347651.png -------------------------------------------------------------------------------- /asset/image-20241026092423031.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026092423031.png -------------------------------------------------------------------------------- /asset/image-20241026092854892.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026092854892.png -------------------------------------------------------------------------------- /asset/image-20241026093411117.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241026093411117.png -------------------------------------------------------------------------------- /asset/image-20241028101632477.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028101632477.png -------------------------------------------------------------------------------- /asset/image-20241028101941532.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028101941532.png -------------------------------------------------------------------------------- /asset/image-20241028102143396.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028102143396.png -------------------------------------------------------------------------------- /asset/image-20241028102417340.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028102417340.png -------------------------------------------------------------------------------- /asset/image-20241028102749892.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028102749892.png -------------------------------------------------------------------------------- /asset/image-20241028104941671.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028104941671.png -------------------------------------------------------------------------------- /asset/image-20241028104955121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028104955121.png -------------------------------------------------------------------------------- /asset/image-20241028105237157.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028105237157.png -------------------------------------------------------------------------------- /asset/image-20241028105856732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028105856732.png -------------------------------------------------------------------------------- /asset/image-20241028105938427.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241028105938427.png -------------------------------------------------------------------------------- /asset/image-20241029125857965.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241029125857965.png -------------------------------------------------------------------------------- /asset/image-20241029131052859.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241029131052859.png -------------------------------------------------------------------------------- /asset/image-20241029134809824.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241029134809824.png -------------------------------------------------------------------------------- /asset/image-20241029135030924.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241029135030924.png -------------------------------------------------------------------------------- /asset/image-20241030204302345.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241030204302345.png -------------------------------------------------------------------------------- /asset/image-20241030205122962.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241030205122962.png -------------------------------------------------------------------------------- /asset/image-20241030205235355.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/asset/image-20241030205235355.png -------------------------------------------------------------------------------- /clean-architecture/.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /clean-architecture/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Gradle project-specific cache directory 2 | .gradle 3 | 4 | # Ignore Gradle build output directory 5 | build 6 | -------------------------------------------------------------------------------- /clean-architecture/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | # Zeppelin ignored files 10 | /ZeppelinRemoteNotebooks/ 11 | -------------------------------------------------------------------------------- /clean-architecture/.idea/aws.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /clean-architecture/.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /clean-architecture/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /clean-architecture/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /clean-architecture/.idea/jpa-buddy.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /clean-architecture/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /clean-architecture/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /clean-architecture/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/clean-architecture/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /clean-architecture/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /clean-architecture/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/7.2/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'clean-architecture' 11 | -------------------------------------------------------------------------------- /clean-architecture/src/main/java/io/reflectoring/buckpal/BuckPalConfigurationProperties.java: -------------------------------------------------------------------------------- 1 | package io.reflectoring.buckpal; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | @Data 7 | @ConfigurationProperties(prefix = "buckpal") 8 | public class BuckPalConfigurationProperties { 9 | 10 | private long transferThreshold = Long.MAX_VALUE; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /clean-architecture/src/main/java/io/reflectoring/buckpal/BuckpelApplication.java: -------------------------------------------------------------------------------- 1 | package io.reflectoring.buckpal; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class BuckpelApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(BuckpelApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /clean-architecture/src/main/java/io/reflectoring/buckpal/MoneyTransferProperties.java: -------------------------------------------------------------------------------- 1 | package io.reflectoring.buckpal; 2 | 3 | import io.reflectoring.buckpal.account.domain.Money; 4 | 5 | public class MoneyTransferProperties { 6 | public MoneyTransferProperties(Money of) { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /clean-architecture/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | buckpal: 2 | transferThreshold: 10000 3 | -------------------------------------------------------------------------------- /microservice-pattern/11장_프로덕션_레디_서비스개발_.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/microservice-pattern/11장_프로덕션_레디_서비스개발_.pdf -------------------------------------------------------------------------------- /microservice-pattern/API Composition과 CQRS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/microservice-pattern/API Composition과 CQRS.pdf -------------------------------------------------------------------------------- /monolith-to-microservices/3_모놀리스를_그대로_둘_것인가?_바꿀_것인가?.md: -------------------------------------------------------------------------------- 1 | 기존의 모놀리스를 마이크로서비스로 변경한다고 했을 때, 어떻게 할 수 있을까? 2 | 3 | 4 | 5 | ## 잘라 내기, 복사 또는 재구현? 6 | 7 | - 모놀리스에서 코드를 **복사하기** 를 원하지만, 최소한 당장은 모놀리스 자체에서 이 기능을 제거하고 싶지는 않다는 점이다. 왜일까? 일정 기간 동안 모놀리스의 기능을 그대로 두면, 여러분에게 더 많은 선택지를 제공하기 때문이다. 이렇게 하면 복원 지점(rollback point)를 확보하거나, 혹은 두 가지 구현을 병행 실행하는 기회를 얻을 수 있다. 8 | 9 | ## 모놀리스 리팩토링 10 | 11 | 새로운 마이크로서비스를 위해 모놀리스에서 가져온 기존 코드를 재사용하는 과정에서 간혹 가장 큰 장벽은 **기존 코드베이스가 전통적으로 비즈니스 도메인 개념을 중심으로 구성되지 않았다는 문제**이다. 12 | 13 | 핵심은, 변경을 원하는 코드 조각 주위에 봉합을 정의하고, 봉합의 새로운 구현 작업을 수행하며, 변경이 이뤄진 후 교체한다. 14 | 15 | 16 | 17 | ## 점진적인 재작성 18 | 19 | 무작정 재구현하는 방법으로 문제를 풀기보다는 항상 먼저 기존 코드베이스를 살리려고 노력하자. 때때로 팀들은 이와 같은 기존 코드 수정만으로 충분한 성과를 거둔다. -------------------------------------------------------------------------------- /objectdesignstyleguide/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' 14 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' 15 | } 16 | 17 | test { 18 | useJUnitPlatform() 19 | } -------------------------------------------------------------------------------- /objectdesignstyleguide/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /objectdesignstyleguide/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'objectdesignstyleguide' 2 | 3 | -------------------------------------------------------------------------------- /user-story/15장_스크럼에서_사용자_스토리_사용하기.md: -------------------------------------------------------------------------------- 1 | # 스크럼에서 사용자 스토리 사용하기 2 | 3 | 스크럼(Scrum)이란? 무엇인가 4 | 5 | ## 스크럼은 반복적이고 점진적이다 6 | 7 | 스크럼은 반복적으로 점진적인 프로세스이다. 8 | 9 | 반복적인 프로세스는 계속적인 정련 작업을 통해 진행되는 프로세스를 의미한다. 10 | 11 | 첫번째 이터 -> 몸통을 만든다. 12 | 두번쨰 이터 -> 간단한 부가기능을 추가한다. 13 | 세번째 이터 -> 에러 처리 부분을 추가한다. 14 | 15 | 이런식으로 말이다. 16 | 17 | 점진적(incremental) 프로세스는 소프트웨어를 여러 부분으로 나누어 각 부분을 개별적으로 개발하고 전달하는 프로세스를 의미한다. 18 | 19 | 20 | ## 스크럼의 기본 21 | 22 | ## 스크럼 팀 23 | 24 | ## 제품 백로그 25 | 26 | ## 스프린트 계획 회의 27 | 28 | ## 스트린트 검토 회의 29 | 30 | ## 일일 스크럼 회의 31 | 32 | ## 스크럼에 스토리 추가하기 33 | 34 | ## 사례 연구 35 | -------------------------------------------------------------------------------- /user-story/Untitled.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [회의록 - 개발] 4 | 5 | 최소한의 기능만 구현한다. 6 | 7 | 상세페이지는 하드코딩으로 만든다. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | **사용자 스토리** 16 | 17 | 유저는 구독주문을 신청할 수 있다. 18 | 19 | 유저는 구독주문을 취소할 수 있다. 20 | 21 | 유저는 구독주문을 확인할 수 있다. 22 | 23 | 24 | 25 | **가장 빠르게 개발할 수 있는 방법은?** 26 | 27 | 28 | 29 | 관리는 최대한 운영으로 풀자. 30 | 31 | 32 | 33 | img -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/1장-사용자 수에 따른 규모 확장성.md: -------------------------------------------------------------------------------- 1 | # 사용자 수에 따른 규모 확장성 2 | 3 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/2장-개략적인 규모 추정.md: -------------------------------------------------------------------------------- 1 | # 개략적인 규모 추정 2 | 3 | 개략적인 규모 추정? 4 | - 보편적으로 통용되는 성능 수치상에서 사고 실험(through experiments)을 행하여 추정치를 계산하는 행위 5 | 6 | 효과적으로 이해하기 위해서는 기본기에 능숙해야 한다. 7 | 8 | 특히 9 | 10 | - 2의 제곱수 11 | 12 | - 응답지연(latency) 값 13 | 14 | - 가용성에 관계된 수치들 15 | 16 | ### 2의 제곱수 17 | 18 | | 2의 x 제곱 | 근사치 | 이름 | 축약형 | 19 | | ---------- | ------ | ----------- | ------ | 20 | | 10 | 1천 | 1킬로바이트 | 1KB | 21 | | 20 | 1백만 | 1메가바이트 | 1MB | 22 | | 30 | 10억 | 1기가바이트 | 1GB | 23 | | 40 | 1조 | 1테라바이트 | 1TB | 24 | | 50 | 1000조 | 1페타바이트 | 1PB | 25 | 26 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/7장-분산시스템을위한유일ID생성기설계.md: -------------------------------------------------------------------------------- 1 | # 분산 시스템을 위한 유일 ID 생성기 설계 2 | 3 | 1) 문제 이해 및 설계 범위 확장 4 | - ID는 유일해야 한다. 5 | - ID는 숫자로만 구성되어야 한다. 6 | - ID는 64비트로 표현될 수 있는 값이어야 한다. 7 | - ID는 발급 날짜에 따라 정렬 가능해야 한다. 8 | - 초당 10,000개의 ID를 만들 수 있어야 한다. 9 | 2) 계략적 설계안 제시 및 동의 구하기 10 | - 다중 마스터 복제 11 | - UUID 12 | - 티켓 서버 13 | - 트위터 스노우플레이크 14 | 3) 상세 설계 15 | 16 | 4) 마무리 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/README.md: -------------------------------------------------------------------------------- 1 | 목차 2 | - [x] 1장 사용자 수에 따른 규모 확장성 3 | - [x] 2장 개략적인규모추정 4 | - [x] 3장 시스템 설계 면접 공략법 5 | - [x] 4장 처리율제한장치의설계 6 | - [x] 5장 안정해시설계 7 | - [x] 6장 키-값저장소설계 8 | - [ ] 7장 분산시스템을위한유일 ID 생성기설계 9 | - [ ] 8장 URL 단축기설계 10 | - [ ] 9장 웹크롤러설계 11 | - [ ] 10장 알림시스템설계 12 | - [ ] 11장 뉴스피드시스템설계 13 | - [ ] 12장 채팅시스템설계 14 | - [ ] 13장 검색어자동완성시스템 15 | - [ ] 14장 유튜브설계 16 | - [ ] 15장 구글드라이브설계 17 | - [ ] 16장 배움은계속된다 18 | 19 | 5장 질문 20 | 21 | 1. 안정해시란 무엇인가요? 22 | - 해시 테이블 크기가 조정될 때 평균적으로 오직 k/n 개의 키만 재배치하는 해시 기술. 여기서 k는 키의 개수이고, n은 슬롯(slot)의 개수. 이와는 달리 대부분의 전통적 해시 테이블은 슬롯의 수가 바뀌면 거의 대부분 키를 재배치한다. 23 | 2. 해시 키 재배치(rehash) 문제는 무엇인가요? 24 | 3. MD5 는 무엇인가요? ?? 25 | 4. https://namu.wiki/w/MD5 26 | 5. 라운드 로빈 방식과 차이점은 무엇인가? -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | out/ 16 | !**/src/main/**/out/ 17 | !**/src/test/**/out/ 18 | 19 | ### Eclipse ### 20 | .apt_generated 21 | .classpath 22 | .factorypath 23 | .project 24 | .settings 25 | .springBeans 26 | .sts4-cache 27 | bin/ 28 | !**/src/main/**/bin/ 29 | !**/src/test/**/bin/ 30 | 31 | ### NetBeans ### 32 | /nbproject/private/ 33 | /nbbuild/ 34 | /dist/ 35 | /nbdist/ 36 | /.nb-gradle/ 37 | 38 | ### VS Code ### 39 | .vscode/ 40 | 41 | ### Mac OS ### 42 | .DS_Store -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | # GitHub Copilot persisted chat sessions 10 | /copilot/chatSessions 11 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/0/b/0ba1b9c7a4878802f938e331cc2d8a042087ec6b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/0/b/0ba1b9c7a4878802f938e331cc2d8a042087ec6b -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/c/a/ca008ce1ad5125494d92c1098a582d3287b5d915: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/c/a/ca008ce1ad5125494d92c1098a582d3287b5d915 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/e/1/e166e6e99e563ffa070e00997ec596a738baf5a9: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/e/1/e166e6e99e563ffa070e00997ec596a738baf5a9 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/e/c/ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/e/c/ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/f/0/f07866736216be0ee2aba49e392191aeae700a35: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/f/0/f07866736216be0ee2aba49e392191aeae700a35 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/f/b/fbe448ebfc3eb2d4e308f6b8b043666f5b57235e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/f/b/fbe448ebfc3eb2d4e308f6b8b043666f5b57235e -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/f/c/fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/f/c/fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/issuestore/index.pb: -------------------------------------------------------------------------------- 1 | 2 | < 3 | build.gradle,f/0/f07866736216be0ee2aba49e392191aeae700a35 4 | S 5 | #src/main/java/org/example/Main.java,0/b/0ba1b9c7a4878802f938e331cc2d8a042087ec6b 6 | [ 7 | +src/main/java/org/example/TimeoutTimer.java,f/c/fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10 8 | U 9 | %src/main/java/org/example/Member.java,e/1/e166e6e99e563ffa070e00997ec596a738baf5a9 10 | U 11 | %src/main/java/org/example/Client.java,c/a/ca008ce1ad5125494d92c1098a582d3287b5d915 12 | F 13 | config/startup_members,e/c/ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6 14 | X 15 | (gradle/wrapper/gradle-wrapper.properties,f/b/fbe448ebfc3eb2d4e308f6b8b043666f5b57235e -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/0/b/0ba1b9c7a4878802f938e331cc2d8a042087ec6b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/0/b/0ba1b9c7a4878802f938e331cc2d8a042087ec6b -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/c/a/ca008ce1ad5125494d92c1098a582d3287b5d915: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/c/a/ca008ce1ad5125494d92c1098a582d3287b5d915 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/e/1/e166e6e99e563ffa070e00997ec596a738baf5a9: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/e/1/e166e6e99e563ffa070e00997ec596a738baf5a9 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/e/c/ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/e/c/ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/f/0/f07866736216be0ee2aba49e392191aeae700a35: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/f/0/f07866736216be0ee2aba49e392191aeae700a35 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/f/b/fbe448ebfc3eb2d4e308f6b8b043666f5b57235e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/f/b/fbe448ebfc3eb2d4e308f6b8b043666f5b57235e -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/f/c/fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/f/c/fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/sonarlint/securityhotspotstore/index.pb: -------------------------------------------------------------------------------- 1 | 2 | < 3 | build.gradle,f/0/f07866736216be0ee2aba49e392191aeae700a35 4 | S 5 | #src/main/java/org/example/Main.java,0/b/0ba1b9c7a4878802f938e331cc2d8a042087ec6b 6 | [ 7 | +src/main/java/org/example/TimeoutTimer.java,f/c/fc38ab6dcdbdd315afaf5e2fc4665db9f3e76f10 8 | U 9 | %src/main/java/org/example/Member.java,e/1/e166e6e99e563ffa070e00997ec596a738baf5a9 10 | U 11 | %src/main/java/org/example/Client.java,c/a/ca008ce1ad5125494d92c1098a582d3287b5d915 12 | F 13 | config/startup_members,e/c/ecb24a9caaa5bc9de01f6c3fbcd51f5db91e5ef6 14 | X 15 | (gradle/wrapper/gradle-wrapper.properties,f/b/fbe448ebfc3eb2d4e308f6b8b043666f5b57235e -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group = 'org.example' 6 | version = '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testImplementation platform('org.junit:junit-bom:5.9.1') 14 | testImplementation 'org.junit.jupiter:junit-jupiter' 15 | } 16 | 17 | test { 18 | useJUnitPlatform() 19 | } -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/config/startup_members: -------------------------------------------------------------------------------- 1 | 192.168.1.101:2222 2 | 192.168.1.102:2222 3 | 192.168.1.103:2222 4 | 192.168.1.104:2222 -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Mar 10 08:15:12 KST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = '_6_gossip' 2 | 3 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/_6_gossip/src/main/java/org/example/Main.java: -------------------------------------------------------------------------------- 1 | package org.example; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | System.out.println("Hello world!"); 6 | } 7 | } -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | # GitHub Copilot persisted chat sessions 10 | /copilot/chatSessions 11 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group = 'com.likelen' 6 | version = '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testImplementation platform('org.junit:junit-bom:5.9.1') 14 | testImplementation 'org.junit.jupiter:junit-jupiter' 15 | } 16 | 17 | test { 18 | useJUnitPlatform() 19 | } -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Mar 02 08:37:00 KST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'consistenthash' 2 | 3 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/consistenthash/src/main/java/com/likelen/Main.java: -------------------------------------------------------------------------------- 1 | package com.likelen; 2 | 3 | class Main { 4 | } 5 | -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/image-1.png -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/image-2.png -------------------------------------------------------------------------------- /가상면접 사례로 배우는 대규모 시스템 설계 기초/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/가상면접 사례로 배우는 대규모 시스템 설계 기초/image.png -------------------------------------------------------------------------------- /반응형웹CSS/1장.가변그리드.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/반응형웹CSS/1장.가변그리드.pdf -------------------------------------------------------------------------------- /반응형웹CSS/3장.미디어쿼리와포트.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/반응형웹CSS/3장.미디어쿼리와포트.pdf -------------------------------------------------------------------------------- /반응형웹CSS/4장.플렉서블박스.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/반응형웹CSS/4장.플렉서블박스.pdf -------------------------------------------------------------------------------- /반응형웹CSS/반응형웹개요.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/반응형웹CSS/반응형웹개요.pdf -------------------------------------------------------------------------------- /분산 컴퓨팅/1장 분산 컴퓨팅이란 무엇인가?.md: -------------------------------------------------------------------------------- 1 | # 분산 컴퓨팅이란 무엇인가? 2 | 3 | 분산 컴퓨팅을 어떻게 설명할 수 있을까? 4 | 5 | > 분산적으로 컴퓨팅한다는 것은 작업을 수행하는 전자/기계 장치들이 네트워크에 연결되어 서로 메시지를 주고받으면서 협의 과정을 거쳐 어떤 목적 달성을 위하여 함께 작업을 수행하는 것 6 | 7 | - '비동기적인 통신'이란 네트워크를 통해서 보내진 메시지가 종착지에 정해진 시간에 도달하는 것을 보장할 수 없는 통신을 말한다. 8 | - 비동기적인 통신 방식으로 서로 메시지를 주고받은 두 분산된 컴퓨팅 장치는 완전한 합의에 이를 수 없다. 9 | - '잘 전달하는 것'과 '협의를 통해서 의사결정'하는 것은 다른 문제다. 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /생각하는_프로그램/column1-조개껍질깨기.md: -------------------------------------------------------------------------------- 1 | # 조개껍질 깨기 -------------------------------------------------------------------------------- /언카피어블(uncopyable)/README.md: -------------------------------------------------------------------------------- 1 | 2 | > 해당 글은 짐 매캘 **언카피어블** 라는 책을 읽고 일부분을 갈무리하는 내용 입니다. 자세한 사항은 [YES 24 클린 코드 - 애자일 소프트웨어 장인 정신](http://www.yes24.com/Product/Goods/94875170) 에서 확인해주세요. 3 | 4 | #### **언카피어블** - 아마존을 이긴 스타트업의 따라 할 수 없는 비즈니스 전략 (짐 매켈비) 5 | 6 | ![](https://tva1.sinaimg.cn/middle/e6c9d24egy1h1bqv9nevjj20nk0xc42j.jpg) 7 | 8 | 9 | - 리더스북 10 | - 지은이: 짐 매켈비 11 | - 옮긴이: 정지현 12 | 13 | -------------------------------------------------------------------------------- /자바 병렬 프로그래밍/README.md: -------------------------------------------------------------------------------- 1 | 1장 들어가며 2 | 3 | - [x] 1부 기본 원리 4 | - [x] 2장 스레드 안전성 5 | - [x] 3장 객체 공유 6 | - [x] 4장 객체 구성 7 | - [x] 5장 프로그래밍 단위 8 | 9 | 2부 병렬 프로그램 구조 잡기 10 | - [x] 6장 작업 실행 11 | - [x] 7장 중단 및 종료 12 | - [x] 8장 스레드 풀 활용 13 | - [x] 9장 GUI 애플리케이션 14 | 15 | 3부 가용성, 성능, 테스트 16 | - [x] 10장 가용성을 최대로 높이기 17 | - [x] 11장 성능, 확장성 18 | - [x] 12장 병렬 프로그램 테스트 19 | 20 | 4부 고급 주제 21 | - [x] 13장 명시적인 락 22 | - [x] 14장 전용 동기화 기능 구현 23 | - [x] 15장 단일 연산 변수와 넌블로킹 동기화 24 | - [x] 16장 자바 메모리 모델 25 | 26 | 부록 A 병렬 프로그램을 위한 어노테이션 27 | 28 | https://jcip.net/listings -------------------------------------------------------------------------------- /자바 병렬 프로그래밍/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/자바 병렬 프로그래밍/img.png -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | test { 13 | useJUnitPlatform() 14 | } 15 | 16 | dependencies { 17 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' 18 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' 19 | 20 | testImplementation 'org.hamcrest:hamcrest-library:2.1' 21 | } -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Pragmatic-unit-testing-in-java-with-junit' 2 | 3 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/main/java/ch01/Scoreable.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Pragmatic Unit Testing in Java with JUnit", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/utj2 for more book information. 8 | ***/ 9 | package ch01; 10 | 11 | @FunctionalInterface 12 | public interface Scoreable { 13 | int getScore(); 14 | } 15 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/main/java/ch02/Scoreable.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Pragmatic Unit Testing in Java with JUnit", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/utj2 for more book information. 8 | ***/ 9 | package ch02; 10 | 11 | @FunctionalInterface 12 | public interface Scoreable { 13 | int getScore(); 14 | } 15 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/main/java/ch16/iloveyouboss/BearingOutOfRangeException.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Pragmatic Unit Testing in Java with JUnit", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/utj2 for more book information. 8 | ***/ 9 | package ch16.iloveyouboss; 10 | 11 | public class BearingOutOfRangeException extends RuntimeException { 12 | private static final long serialVersionUID = 1L; 13 | } 14 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/main/java/ch16/iloveyouboss/Scoreable.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Pragmatic Unit Testing in Java with JUnit", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/utj2 for more book information. 8 | ***/ 9 | package ch16.iloveyouboss; 10 | 11 | @FunctionalInterface 12 | public interface Scoreable { 13 | int getScore(); 14 | } 15 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/main/java/ch16/transmission/Gear.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Pragmatic Unit Testing in Java with JUnit", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/utj2 for more book information. 8 | ***/ 9 | package ch16.transmission; 10 | 11 | public enum Gear { 12 | DRIVE, PARK 13 | 14 | } 15 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/main/java/ch16/transmission/Moveable.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Pragmatic Unit Testing in Java with JUnit", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/utj2 for more book information. 8 | ***/ 9 | package ch16.transmission; 10 | 11 | public interface Moveable { 12 | int currentSpeedInMph(); 13 | } 14 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/test/java/ch01/ScoreCollectionTest.java: -------------------------------------------------------------------------------- 1 | package ch01; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.hamcrest.MatcherAssert.assertThat; 6 | import static org.hamcrest.Matchers.equalTo; 7 | 8 | 9 | class ScoreCollectionTest { 10 | 11 | @Test 12 | void name() { 13 | // Arrange 14 | ScoreCollection collection = new ScoreCollection(); 15 | collection.add(() -> 5); 16 | collection.add(() -> 7); 17 | // Act 18 | int actual = collection.arithmeticMean(); 19 | 20 | // Assert 21 | assertThat(actual, equalTo(6)); 22 | } 23 | } -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/Pragmatic-unit-testing-in-java-with-junit/src/test/java/ch16/scratch/ExpectToFail.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Pragmatic Unit Testing in Java with JUnit", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/utj2 for more book information. 8 | ***/ 9 | package ch16.scratch; 10 | 11 | import java.lang.annotation.*; 12 | 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target({ElementType.METHOD}) 15 | 16 | public @interface ExpectToFail { 17 | } 18 | -------------------------------------------------------------------------------- /자바와-JUnit을-활용한-실용주의-단위테스트/docs/ch08-깔끔한-코드로-리팩토링하기.md: -------------------------------------------------------------------------------- 1 | ```text 2 | ... 중복된 코드 조각이 늘면 유지 보수 비용도 증가하고 변경에 대한 리스크도 함꼐 늘어납니다. 그래서 시스템에 있는 중복의 양을 최소화하려고 합니다. ... 3 | ... 코드를 이해하는 비용 또한 상당합니다. 깔끔하고 좋은 구조를 갖춘 코드는 10분이면 변경할 수 있지만, 복잡하고 지저분한 코드는 몇 시간이 필요합니다. 따라서 시스템의 명확성도 극대화하고 싶습니다. ... 4 | 5 | 낮은 중복성과 높은 명확성이라는 두 가지 목표를 합리적인 비용과 놀라운 투자 수익률(ROI)로 달성할 수 있는 방법은 단위 테스트를 만들면서 도달할 수 있습니다. 6 | ``` 7 | 8 | -------------------------------------------------------------------------------- /진화적 아키텍쳐(BuildingEvolutionaryArchitechtures)/CH4-아키텍처 커버넌스 자동화.md: -------------------------------------------------------------------------------- 1 | # 아키텍쳐 커버넌스 자동화 2 | 3 | 커버넌스가 뭐지? 4 | 5 | 6 | 아키텍쳐 커버넌스 > 소프트웨어 엔지너어링 관행의 진화를 상징하는 거버넌스 자동화. 7 | 8 | 개발자 수준의 고립을 강요했던 과거 9 | 10 | 11 | 12 | 비효율적이고 반복적인 수작업은 아키텍처에서도 존재. 그러므로 피트니스 함수를 지속적 통합과 결부시킴으로써 아키텍트는 메트릭과 커버넌스 검사를 정기적인 무결성 검증 절차로 전환할 수 있다. 13 | 14 | 15 | 16 | **피트니스 함수는 저수준 코드 기반 분석에서 엔터프라이즈 아키텍쳐에 이르기까지 모든 아키텍쳐 측면에 존재.** 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /켄트백의-구현패턴/1_개관.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/켄트백의-구현패턴/1_개관.jpeg -------------------------------------------------------------------------------- /켄트백의-구현패턴/2_개관2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/켄트백의-구현패턴/2_개관2.jpeg -------------------------------------------------------------------------------- /켄트백의-구현패턴/3_패턴.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/켄트백의-구현패턴/3_패턴.jpeg -------------------------------------------------------------------------------- /켄트백의-구현패턴/4_1_프로그래밍_이론.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/켄트백의-구현패턴/4_1_프로그래밍_이론.jpeg -------------------------------------------------------------------------------- /켄트백의-구현패턴/4_2_프로그래밍_이론.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/켄트백의-구현패턴/4_2_프로그래밍_이론.jpeg -------------------------------------------------------------------------------- /켄트백의-구현패턴/4_3_프로그래밍_이론.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LenKIM/Book/2c194172500688b9d7fe619278e16dda44445c91/켄트백의-구현패턴/4_3_프로그래밍_이론.jpeg -------------------------------------------------------------------------------- /켄트백의-구현패턴/README.md: -------------------------------------------------------------------------------- 1 | # 켄트벡의 구현 패턴 2 | 3 | 1장 소개 4 | 2장 패턴 5 | 3장 프로그래밍 이론 6 | 4장 동기유발 7 | 5장 클래스 8 | 6장 상태 9 | 7장 행위 10 | 8장 메소드 11 | 9장 컬렉션 12 | 10장 발전하는 프레임워크 13 | 부록 A 성능 측정 -------------------------------------------------------------------------------- /코어논리학/README.md: -------------------------------------------------------------------------------- 1 | - [x] 01강 논증이란 무엇인가?1 2 | - [x] 02강 연역논증과 귀납논증1 3 | - [x] 03강 연역논증과 귀납논증1 4 | - [x] 04강 연역논증과 귀납논증1 5 | - [x] 05강 논리적 연결사1 6 | - [ ] 06강 문장논리 언어와 진리표를 이용한 타당성 증명1 7 | - [ ] 07강 문장논리 언어와 진리표를 이용한 타당성 증명1 8 | - [ ] 08강 조건문, 쌍조건문, 필요조건, 충분조건1 9 | - [ ] 09강 조건문, 쌍조건문, 필요조건, 충분조건1 10 | - [ ] 10강 문장논리 1 : 자연연역에 의한 타당성 증명1 11 | - [ ] 11강 자연연역에 의한 타당성 증명1 12 | - [ ] 12강 문장논리 2 : 파생규칙1 13 | - [ ] 13강 술어논리 1 : 술어논리의 언어1 14 | - [ ] 14강 술어논리 1 : 술어논리의 언어1 15 | - [ ] 15강 술어논리 2 : 의미론과 타당성1 16 | - [ ] 16강 술어논리 2 : 의미론과 타당성1 17 | - [ ] 17강 다중양화문장1 18 | - [ ] 18강 다중양화문장1 19 | - [ ] 19강 다중양화문장1 20 | - [ ] 20강 술어논리의 자연연역1 21 | - [ ] 21강 술어논리의 자연연역1 22 | - [ ] 22강 술어논리의 자연연역1 23 | - [ ] 23강 술어논리의 자연연역1 24 | - [ ] 24강 동일성문장과 확정기술어구0 -------------------------------------------------------------------------------- /패턴을_활용한_리팩토링/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 01장_ 이책을 쓴 이유 3 | 02장_ 리팩터링 4 | 03장_ 패턴 5 | 04장_ 코드 속의 냄새 6 | 05장_ 패턴을 고려한 리팩터링 카탈로그 7 | 06장_ 생성 8 | 07장_ 단순화 9 | 08장_ 일반화 10 | 09장_ 보호 11 | 10장_ 축적 12 | 11장_ 유틸리티 13 | ``` -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/color_dispatch/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns color_dispatch.core_test 2 | (:require [clojure.test :refer :all] 3 | [color_dispatch.core :refer :all])) 4 | 5 | (deftest pure-colors 6 | (is (= "Red: 5" (color-string (struct color 5 0 0)))) 7 | (is (= "Green: 12" (color-string (struct color 0 12 0)))) 8 | (is (= "Blue: 40" (color-string (struct color 0 0 40))))) 9 | 10 | (deftest varied-colors 11 | (is (= "Red:5, Green: 40, Blue: 6" (color-string (struct color 5 40 6))))) 12 | 13 | (run-all-tests) 14 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/letter-grades/lettergrades.clj: -------------------------------------------------------------------------------- 1 | (ns lettergrades) 2 | 3 | (defn in [score low high] 4 | (and (number? score) (<= low score high))) 5 | 6 | (defn letter-grade [score] 7 | (cond 8 | (in score 90 100) "A" 9 | (in score 80 90) "B" 10 | (in score 70 80) "C" 11 | (in score 60 70) "D" 12 | (in score 0 60) "F" 13 | (re-find #"[ABCDFabcdf]" score) (.toUpperCase score))) 14 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/letter-grades/lettergradestest.clj: -------------------------------------------------------------------------------- 1 | (ns lettergradestest 2 | (:use clojure.test) 3 | (:use lettergrades)) 4 | 5 | (deftest numeric-letter-grades 6 | (dorun (map #(is (= "A" (letter-grade %))) (range 90 100))) 7 | (dorun (map #(is (= "B" (letter-grade %))) (range 80 89))) 8 | (dorun (map #(is (= "C" (letter-grade %))) (range 70 79))) 9 | (dorun (map #(is (= "D" (letter-grade %))) (range 60 69))) 10 | (dorun (map #(is (= "F" (letter-grade %))) (range 0 59)))) 11 | 12 | (deftest string-letter-grades 13 | (dorun (map #(is (= (.toUpperCase %) 14 | (letter-grade %))) ["A" "B" "C" "D" "F" "a" "b" "c" "d" "f"]))) 15 | 16 | (run-all-tests) 17 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/name-hash/core.clj: -------------------------------------------------------------------------------- 1 | (ns name-hash.core) 2 | (use '[clojure.string :only (join split)]) 3 | 4 | 5 | (let [alpha (into #{} (concat (map char (range (int \a) (inc (int \z)))) 6 | (map char (range (int \A) (inc (int \Z)))))) 7 | rot13-map (zipmap alpha (take 52 (drop 26 (cycle alpha))))] 8 | 9 | (defn rot13 10 | "Given an input string, produce the rot 13 version of 11 | the string. \"hello\" -> \"uryyb\"" 12 | [s] 13 | (apply str (map #(get rot13-map % %) s)))) 14 | 15 | (defn name-hash [name] 16 | (apply str (map #(rot13 %) (split name #"\d")))) 17 | 18 | (def name-hash-m (memoize name-hash)) 19 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/palindromes/palindromes.clj: -------------------------------------------------------------------------------- 1 | (defn palindrome? [s] 2 | (let [sl (.toLowerCase s)] 3 | (= sl (apply str (reverse sl))))) 4 | 5 | (defn find-palindromes [s] 6 | (filter palindrome? (clojure.string/split s #" "))) 7 | 8 | (println (find-palindromes "The quick brown fox jumped over anna the dog")) 9 | ; (anna) 10 | (println (find-palindromes "Bob went to Harrah and gambled with Otto and Steve")) 11 | ; (Bob Harrah Otto) 12 | (println (take 1 (find-palindromes "Bob went to Harrah with Otto and Steve"))) 13 | ; (Bob) 14 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/primes/core.clj: -------------------------------------------------------------------------------- 1 | (ns primes.core) 2 | 3 | (defn factors [n] 4 | (filter #(zero? (rem n %)) (range 1 (inc n)))) 5 | 6 | (defn sum-factors [n] 7 | (reduce + (factors n))) 8 | 9 | (defn prime? [n] 10 | (= (inc n) (sum-factors n))) 11 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/trans/core.clj: -------------------------------------------------------------------------------- 1 | (ns trans.core 2 | (:require [clojure.string :as s])) 3 | 4 | ; BEGIN clj_process (2-6) 5 | (defn process [list-of-emps] 6 | (reduce str (interpose "," 7 | (map s/capitalize (filter #(< 1 (count %)) list-of-emps))))) 8 | ; END clj_process 9 | 10 | ; BEGIN clj_process_thread (2-7) 11 | (defn process2 [list-of-emps] 12 | (->> list-of-emps 13 | (filter #(< 1 (count %))) 14 | (map s/capitalize) 15 | (interpose ",") 16 | (reduce str))) 17 | ; END clj_process_thread 18 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/clojure/xml.clj: -------------------------------------------------------------------------------- 1 | (use 'clojure.xml) 2 | 3 | (def WEATHER-URI "https://query.yahooapis.com/v1/public/yql?q=select * from weather.forecast where woeid=%d&format=xml") 4 | 5 | (defn get-location [city-code] 6 | (for [x (xml-seq (parse (format WEATHER-URI city-code))) 7 | :when (= :yweather:location (:tag x))] 8 | (str (:city (:attrs x)) "," (:region (:attrs x))))) 9 | 10 | (defn get-temp [city-code] 11 | (for [x (xml-seq (parse (format WEATHER-URI city-code))) 12 | :when (= :yweather:condition (:tag x))] 13 | (:temp (:attrs x)))) 14 | 15 | (println "weather for " (get-location 12770744) "is " (get-temp 12770744)) 16 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/as_demo.groovy: -------------------------------------------------------------------------------- 1 | h = [hasNext: { h.i > 0 }, next: {h.i--}] 2 | h.i = 10 // <1> 3 | def pseudoIterator = h as Iterator // <2> 4 | 5 | while (pseudoIterator.hasNext()) 6 | print pseudoIterator.next() + (pseudoIterator.hasNext() ? ", " : "\n") 7 | // 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 8 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/make_counter.groovy: -------------------------------------------------------------------------------- 1 | def Closure makeCounter() { 2 | def local_variable = 0 3 | return { return local_variable += 1 } // <1> 4 | } 5 | 6 | c1 = makeCounter() // <2> 7 | c1() // <3> 8 | c1() 9 | c1() 10 | 11 | c2 = makeCounter() // <4> 12 | 13 | println "C1 = ${c1()}, C2 = ${c2()}" 14 | // output: C1 = 4, C2 = 1 // <5> 15 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/memoize_hashing/NameHash.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.memoize_hashing 2 | 3 | class NameHash { 4 | def static hash = {name -> 5 | name.collect{rot13(it)}.join() 6 | }.memoize() 7 | 8 | public static char rot13(s) { 9 | char c = s 10 | switch (c) { 11 | case 'A'..'M': 12 | case 'a'..'m': return c + 13 13 | case 'N'..'Z': 14 | case 'n'..'z': return c - 13 15 | default: return c 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/memoize_hashing/NameHashTest.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.memoize_hashing 2 | 3 | class NameHashTest extends GroovyTestCase { 4 | void testHash() { 5 | assertEquals("ubzre", NameHash.hash.call("homer")) } 6 | } 7 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/palindromes/Palindromes.groovy: -------------------------------------------------------------------------------- 1 | def isPalindrome(s) { 2 | def sl = s.toLowerCase() 3 | sl == sl.reverse() 4 | } 5 | 6 | def findFirstPalindrome(s) { 7 | s.tokenize(' ').find {isPalindrome(it)} 8 | } 9 | 10 | s1 = "The quick brown fox jumped over anna the dog"; 11 | println(findFirstPalindrome(s1)) // anna 12 | s2 = "Bob went to Harrah and gambled with Otto and Steve" 13 | println(findFirstPalindrome(s2)) // Bob 14 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/polydispatch/LetterGrade.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.polydispatch 2 | 3 | class LetterGrade { 4 | def gradeFromScore(score) { 5 | switch (score) { 6 | case 90..100 : return "A" 7 | case 80..<90 : return "B" 8 | case 70..<80 : return "C" 9 | case 60..<70 : return "D" 10 | case 0..<60 : return "F" 11 | case ~"[ABCDFabcdf]" : return score.toUpperCase() 12 | default: throw new IllegalArgumentException("Invalid score: ${score}") 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/polydispatch/LetterGradeTest.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.polydispatch 2 | 3 | import org.junit.Test 4 | import com.nealford.ft.polydispatch.LetterGrade 5 | 6 | import static org.junit.Assert.assertEquals 7 | 8 | class LetterGradeTest { 9 | @Test 10 | public void test_letter_grades() { 11 | def lg = new LetterGrade() 12 | assertEquals("A", lg.gradeFromScore(92)) 13 | assertEquals("B", lg.gradeFromScore(85)) 14 | assertEquals("D", lg.gradeFromScore(65)) 15 | assertEquals("F", lg.gradeFromScore("f")) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/template/Customer.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.template 2 | 3 | abstract class Customer { 4 | def plan 5 | 6 | def Customer() { 7 | plan = [] 8 | } 9 | 10 | def abstract checkCredit() 11 | def abstract checkInventory() 12 | def abstract ship() 13 | 14 | def process() { 15 | checkCredit() 16 | checkInventory() 17 | ship() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/template/CustomerBlocks.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.template 2 | 3 | class CustomerBlocks { 4 | def plan, checkCredit, checkInventory, ship 5 | 6 | def CustomerBlocks() { 7 | plan = [] 8 | } 9 | 10 | def process() { 11 | checkCredit() 12 | checkInventory() 13 | ship() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/template/CustomerBlocksWithProtection.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.template 2 | 3 | class CustomerBlocksWithProtection { 4 | def plan, checkCredit, checkInventory, ship 5 | 6 | def CustomerBlocksWithProtection() { 7 | plan = [] 8 | } 9 | // BEGIN groovy_customer_blocks 10 | def process() { 11 | checkCredit?.call() 12 | checkInventory?.call() 13 | ship?.call() 14 | } 15 | // END groovy_customer_blocks 16 | } 17 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/groovy/com/nealford/ft/trans/TheCompanyProcess.groovy: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.trans 2 | 3 | class TheCompanyProcess { 4 | // BEGIN groovy_process 5 | public static String cleanUpNames(listOfNames) { 6 | listOfNames 7 | .findAll { it.length() > 1 } 8 | .collect { it.capitalize() } 9 | .join ',' 10 | } 11 | // END groovy_process 12 | 13 | } 14 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/java/com/nealford/ft/composition/FPrime.java: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.composition; 2 | 3 | import java.util.Set; 4 | 5 | // BEGIN java_fprime 6 | public class FPrime { 7 | 8 | public static boolean isPrime(int number) { 9 | Set factors = Factors.of(number); 10 | return number > 1 && 11 | factors.size() == 2 && 12 | factors.contains(1) && 13 | factors.contains(number); 14 | } 15 | } 16 | // END java_fprime 17 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/java/com/nealford/ft/composition/PrimeBeta.java: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.composition; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | // BEGIN java_prime_beta 7 | public class PrimeBeta extends FactorsBeta { 8 | public PrimeBeta(int number) { 9 | super(number); 10 | } 11 | 12 | public boolean isPrime() { 13 | Set primeSet = new HashSet() {{ 14 | add(1); add(number);}}; 15 | return getFactors().equals(primeSet); 16 | } 17 | 18 | } 19 | // END java_prime_beta 20 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/java/com/nealford/ft/errorhandling/F.java: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.errorhandling; 2 | 3 | public interface F { 4 | public void f(A input); 5 | } 6 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/java/com/nealford/ft/number_classifier_functional_java/NumberStuff.java: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.number_classifier_functional_java; 2 | 3 | import fj.F2; 4 | import fj.data.List; 5 | 6 | public class NumberStuff { 7 | // BEGIN java_foldleft_criteria 8 | static public int addOnlyOddNumbersIn(List numbers) { 9 | return numbers.foldLeft(new F2() { 10 | public Integer f(Integer i1, Integer i2) { 11 | return (!(i2 % 2 == 0)) ? i1 + i2 : i1; 12 | } 13 | }, 0); 14 | // END java_foldleft_criteria 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/java/com/nealford/ft/primes/PrimeIterator.java: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.primes; 2 | 3 | import java.util.Iterator; 4 | 5 | public class PrimeIterator implements Iterator { 6 | private int lastPrime = 1; 7 | 8 | @Override 9 | public boolean hasNext() { 10 | return true; 11 | } 12 | 13 | @Override 14 | public Integer next() { 15 | return lastPrime = Prime.nextPrimeFrom(lastPrime); 16 | } 17 | 18 | @Override 19 | public void remove() { 20 | throw new RuntimeException("Fundamental nature of the universe exception!"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/java/com/nealford/ft/trans/TheCompanyProcess.java: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.trans; 2 | 3 | import java.util.List; 4 | 5 | public class TheCompanyProcess { 6 | public String cleanNames(List listOfNames) { 7 | StringBuilder result = new StringBuilder(); 8 | for(int i = 0; i < listOfNames.size(); i++) { 9 | if (listOfNames.get(i).length() > 1) { 10 | result.append(capitalizeString(listOfNames.get(i))).append(","); 11 | } 12 | } 13 | return result.substring(0, result.length() - 1).toString(); 14 | } 15 | 16 | public String capitalizeString(String s) { 17 | return s.substring(0, 1).toUpperCase() + s.substring(1, s.length()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/scala/com/nealford/ft/currying/CurryTest.scala: -------------------------------------------------------------------------------- 1 | object CurryTest extends App { 2 | 3 | def filter(xs: List[Int], p: Int => Boolean): List[Int] = 4 | if (xs.isEmpty) xs 5 | else if (p(xs.head)) xs.head :: filter(xs.tail, p) 6 | else filter(xs.tail, p) 7 | 8 | def dividesBy(n: Int)(x: Int) = ((x % n) == 0) // <1> 9 | 10 | val nums = List(1, 2, 3, 4, 5, 6, 7, 8) 11 | println(filter(nums, dividesBy(2))) // <2> 12 | println(filter(nums, dividesBy(3))) 13 | } 14 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/scala/com/nealford/ft/number_classifier/NumberClassifier.scala: -------------------------------------------------------------------------------- 1 | package com.nealford.ft.number_classifier 2 | 3 | // BEGIN Number_Classifier_Scala 4 | object NumberClassifier { 5 | def isFactor(factor: Int, number: Int) = 6 | number % factor == 0 7 | 8 | def factors(number: Int) = 9 | (1 to number) filter (isFactor(_, number)) 10 | 11 | def sum(factors : Seq[Int]) = 12 | factors.foldLeft(0)(_ + _) 13 | 14 | def isPerfect(number: Int) = 15 | sum(factors(number)) - number == number 16 | 17 | def isAbundant(number: Int) = 18 | sum(factors(number)) - number > number 19 | 20 | def isDeficient(number: Int) = 21 | sum(factors(number)) - number < number 22 | } 23 | // END Number_Classifier_Scala 24 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/scala/com/nealford/ft/palimdromes/Palindromes.scala: -------------------------------------------------------------------------------- 1 | def isPalindrome(x: String) = x == x.reverse 2 | def findPalindrome(s: Seq[String]) = s find isPalindrome 3 | 4 | val sentence = "Bobby went to Harrah and gambled with Otto and Steve" 5 | val words = sentence.toLowerCase().split(" ") 6 | println(findPalindrome(words take 1)) // None 7 | println(findPalindrome(words take 4)) // Some(harrah) 8 | -------------------------------------------------------------------------------- /함수형사고(Functional Thinking)/FP_Book_Source/scala/com/nealford/ft/xml.scala: -------------------------------------------------------------------------------- 1 | import scala.xml._ 2 | import java.net._ 3 | import scala.io.Source 4 | 5 | val theUrl = "https://query.yahooapis.com/v1/public/yql?q=select+*+from+weather.forecast+where+woeid=12770744&format=xml" 6 | 7 | val xmlString = Source.fromURL(new URL(theUrl)).mkString 8 | val xml = XML.loadString(xmlString) 9 | val city = xml \\ "location" \\ "@city" 10 | val state = xml \\ "location" \\ "@region" 11 | val temperature = xml \\ "condition" \\ "@temp" 12 | 13 | println(city + ", " + state + " " + temperature) 14 | --------------------------------------------------------------------------------