문제

나이 오래된 질문입니다.어디에 당신의 사업을 논리,데이터베이스에 저장된 절차(또는 패키지),또는에서 응용 프로그램/중 층?그리고 더 중요한 것은,왜?

가정 데이터베이스로 자립하는 것을 목표로하고 있지 않습니다.

도움이 되었습니까?

해결책

데이터가 일관되고 올바른지 확인하기 위해 데이터베이스에 비즈니스 로직을 충분히 넣으십시오.

그러나 사용자 경험을 향상시키기 위해이 논리의 일부를 다른 수준에서 복제 할 필요가 없습니다.

다른 팁

비즈니스 논리가 어디로 가야하는지 결정할 때 코드의 유지 관리 가능성은 항상 큰 관심사입니다.

통합 디버깅 도구와보다 강력한 IDE는 일반적으로 저장 프로 시저에서 동일한 코드보다 중간 계층 코드를 더 쉽게 유지할 수 있습니다. 그렇지 않으면 실제 이유가 없다면 저장된 절차가 아닌 중간 계층/응용 프로그램에서 비즈니스 로직으로 시작해야합니다.

그러나보고 및 데이터 마이닝/검색에 올 때 저장된 절차가 종종 더 나은 선택이 될 수 있습니다. 이는 데이터베이스 집계/필터링 기능의 성능과 데이터 소스를 매우 가깝게 처리하고 있다는 사실 덕분입니다. 그러나 이것은 어쨌든 고전적인 비즈니스 논리를 가장 많이 고려하지 않을 수 있습니다.

매우 간단한 경우에 비즈니스 로직을 저장 절차에 넣을 수 있습니다. 일반적으로 간단한 경우조차도 시간이 지남에 따라 복잡해지는 경향이 있습니다. 데이터베이스에 비즈니스 로직을 넣지 않는 이유는 다음과 같습니다.

데이터베이스에 비즈니스 로직을 넣는 것은 데이터베이스의 기술적 구현에 단단히 연결합니다. 테이블을 변경하면 많은 추가 버그와 추가 테스트가 발생하는 많은 저장 절차를 다시 변경하게됩니다.

일반적으로 UI는 유효성 검사와 같은 비즈니스 로직에 따라 다릅니다. 이러한 것들을 데이터베이스에 넣으면 데이터베이스와 UI 사이에 단단한 커플 링이 발생하거나 다른 경우에는 두 가지 사이의 유효성 검사 로직이 복제됩니다.

동일한 데이터베이스에서 여러 응용 프로그램이 작동하기가 어려워집니다. 하나의 절단에 대한 변경으로 인해 다른 사람이 파손됩니다. 이것은 유지 보수 악몽으로 빠르게 변할 수 있습니다. 그래서 그것은 실제로 확장되지 않습니다.

보다 실질적으로 SQL은 이해할 수있는 방식으로 비즈니스 논리를 구현하는 좋은 언어가 아닙니다. SQL은 세트 기반 작업에 적합하지만 "대규모로 프로그래밍"을위한 구성을 놓치면 많은 양의 저장 절차를 유지하기가 어렵습니다. 현대 OO 언어는 더 적합하고이를 위해 유연합니다.

그렇다고해서 저장된 Procs와보기를 사용할 수 없다는 의미는 아닙니다. 나는 때때로 두 가지를 분리하기 위해 표와 응용 프로그램 사이에 저장된 절차와보기를 추가하는 것이 좋은 생각이라고 생각합니다. 이렇게하면 외부 인터페이스를 변경하지 않고 데이터베이스의 레이아웃을 변경하여 데이터베이스를 독립적으로 리팩터링 할 수 있습니다.

정말 당신에게 달려 있습니다. 일관된 한.

데이터베이스 계층에 넣을 좋은 이유 중 하나 : 고객이 데이터베이스 백엔드를 절대 변경하지 않을 것이라고 확신하는 경우.

애플리케이션 계층에 넣어야 할 좋은 이유 중 하나 : 애플리케이션을 위해 여러 지속성 기술을 목표로하는 경우.

또한 핵심 역량을 고려해야합니다. 개발자는 주로 응용 프로그램 계층 개발자입니까, 아니면 주로 DBA 유형입니까?

응용 프로그램 계층에 비즈니스 로직을 갖는 이점이 있지만 언어/프레임 워크가 데이터베이스보다 자주 변경되는 것처럼 보이고 싶습니다.

내가 지원하는 일부 시스템은 지난 10-15 년 동안 다음 UI를 거쳤습니다. Oracle Forms/Visual Basic/Perl CGI/ASP/Java Servlet. 변경되지 않은 한 가지 - 관계형 데이터베이스 및 저장 절차.

는 없지만 하나 정답에 따라 달라집니다-프로젝트에서 문의 접근 방식을 주창에서"도메인 구동 Design"에릭 에반스.이 방식에서는 비즈니스 로직은 고립 된에서 자신의 계층 도메인 계층 위에 앉아 있는 인프라의 층(들)-포함하는 데이터베이스 코드,그리고 아래는 응용 프로그램 계층,보내는 요청을 도메인으로 레이어에 대한 이행 및 수신하의 확인에 대한 그들의 완성으로,효과적으로 운용합니다.

이 방법,비지니스 로직을 캡처에서 모델이 될 수 있는 논의하는 사람들과 비즈니스를 이해하고 이외에도 기술적인 문제,그리고 그것은 쉽게 격리에서 변경 사업 규칙,자신 기술 구현에 문제가 흐르는 응용 프로그램과 상호 작용하는 비즈니스(도메인)모델이다.

내가 읽는 것이 좋습니다 위의 책 기회를 얻을 경우,당신은 그것에 매우 좋은 방법을 설명하는 이 순수한 이상적인할 수 있는 실제로 근사화의 현실 세계에서 실제 코드와 프로젝트입니다.

이 경우 질문자가 고려해야 할 데이터베이스 독립성은 데이터베이스에서 논리를 빼앗는 가장 강력한 주장입니다. 데이터베이스 독립성에 대한 가장 강력한 주장은 데이터베이스 백엔드를 선호하는 회사에 소프트웨어를 판매하는 능력입니다.

따라서 데이터베이스에서 저장된 절차를 기술적 인 것이 아니라 상업적 인 것으로 간주하기위한 주요 주장을 고려합니다. 기술적 인 이유가있을 수 있지만 성능, 무결성 및 여러 응용 프로그램이 동일한 API를 사용할 수있는 기능 등 기술적 이유가 있습니다.

SP를 사용할지 여부는 사용할 데이터베이스에 의해 크게 영향을받습니다. 데이터베이스 독립성을 고려하지 않으면 T-SQL을 사용하거나 PL/SQL을 사용하는 경험이 매우 다릅니다.

Oracle을 사용하여 응용 프로그램을 개발하는 경우 PL/SQL은 언어로서 명백한 선택입니다. 데이터와 매우 밀접하게 결합되어 모든 릴라제에서 지속적으로 개선되며, 모든 적절한 개발 도구는 CVS 또는 전복 또는 SOMESUCH와 PLP/SQL 개발을 통합 할 것입니다.

Oracle의 웹 기반 Application Express Development Environment는 PL/SQL로 100% 구축되었습니다.

데이터 무결성에 영향을 미치는 것은 데이터베이스 수준에 있어야합니다. 사용자 인터페이스 이외의 다른 것들은 종종 가져 오기, 가격 책정 체계, 핫 수정 등을 포함하여 데이터베이스에서 데이터를 설치, 업데이트 또는 삭제하는 것 등을 항상 따라야하는지 확인 해야하는 경우, 논리를 기본값에 넣으십시오. 그리고 트리거.

이것은 사용자 인터페이스에도 그것을 갖는 것이 좋지 않다고 말하는 것은 아닙니다 (데이터베이스가 받아 들일 수없는 정보를 보내는 이유) 그러나 데이터베이스에서 이러한 것들을 무시하는 것은 법원 재난입니다.

데이터베이스 독립성이 필요한 경우 응용 프로그램 계층에서 사용 가능한 표준이 데이터베이스 계층에서 사용 가능한 것보다 훨씬 더 널리 퍼져 있기 때문에 모든 비즈니스 논리를 응용 프로그램 계층에 넣을 수 있습니다.

그러나 데이터베이스 독립성이 #1 요소가 아니고 팀의 기술에 강력한 데이터베이스 기술이 포함되어 있으면 데이터베이스에 비즈니스 로직을 넣는 것이 최상의 솔루션이 될 수 있습니다. 애플리케이션 담당자가 응용 프로그램 별 작업을 수행하고 데이터베이스 담당자가 모든 쿼리가 날아갈 수 있도록 할 수 있습니다.

물론 SQL 문을 함께 던질 수있는 것과 "강력한 데이터베이스 기술"을 가질 수있는 사이에는 큰 차이가 있습니다. 팀 팀이 후자보다 전자와 더 가까워지면이 세상의 최대 절전 모드 중 하나를 사용하여 응용 프로그램에 논리를 두십시오. (또는 팀을 바꾸십시오!).

내 경험상, 엔터프라이즈 환경에서는이 분야의 단일 대상 데이터베이스와 기술이 있습니다.이 경우 데이터베이스에 할 수있는 모든 것을 넣습니다. 소프트웨어를 판매하는 사업에 종사하는 경우 데이터베이스 라이센스 비용은 데이터베이스 독립성을 가장 큰 요소로 만들고 응용 프로그램 계층에서 할 수있는 모든 것을 구현할 것입니다.

도움이되기를 바랍니다.

오늘날 저장된 PROC 코드를 전복시키고 우수한 도구 지원 으로이 코드를 디버깅하기 위해 제출할 수 있습니다.

SQL 문을 결합한 저장된 Procs를 사용하면 응용 프로그램과 데이터베이스 간의 데이터 트래픽 양을 줄이고 데이터베이스 호출 수를 줄이고 성능이 큰 이점을 얻을 수 있습니다.

우리가 C#에 구축을 시작하면 저장된 Procs를 사용하지 않기로 결정했지만 이제는 저장된 Procs로 점점 더 많은 코드를 이동하고 있습니다. 특히 배치 처리.

그러나 트리거를 사용하지 말고 저장된 Procs 또는 더 나은 패키지를 사용하십시오. 트리거는 유지 관리 가능성을 줄입니다.

응용 프로그램 계층에 코드를 넣으면 DB 독립 응용 프로그램이 발생합니다.

때로는 성능의 이유로 저장된 절차를 사용하는 것이 좋습니다.

(평소와 같이) 응용 프로그램 요구 사항에 따라 다릅니다.

데이터베이스에 들어가는 유일한 것은 데이터입니다.

저장된 절차는 유지 보수 악몽입니다. 그들은 데이터가 아니며 데이터베이스에 속하지 않습니다. 개발자와 DBA의 끝없는 조정은 조직 마찰에 지나지 않습니다.

저장된 절차에 대한 우수한 버전 제어를 유지하기는 어렵습니다. 데이터베이스 외부의 코드는 설치하기가 쉽습니다. 잘못된 버전이 있다고 생각하면 SVN UP (설치)을 수행하고 응용 프로그램이 알려진 상태로 돌아갑니다. 환경 변수, 디렉토리 링크 및 애플리케이션에 대한 많은 환경 제어가 있습니다.

당신은 단순하게 할 수 있습니다 PATH 조작, 다양한 상황에 사용할 수있는 변형 소프트웨어가 있습니다 (교육, 테스트, QA, 생산, 고객 별 개선 등).

그러나 데이터베이스 내부의 코드는 관리하기가 훨씬 어렵습니다. "경로", 디렉토리 링크 또는 기타 환경 변수 등의 적절한 환경이 없습니다. 데이터베이스에 붙어있는 영구적 인 전 세계적으로 바인딩 된 응용 프로그램 소프트웨어 세트가 있으며 데이터와 결혼했습니다.

트리거는 더 나쁩니다. 그들은 유지 보수와 디버깅 악몽입니다. 나는 그들이 어떤 문제를 해결하는지 알지 못한다. 그들은 누군가가 사용 가능한 클래스 (또는 기능 라이브러리)를 올바르게 사용하기 위해 귀찮게 할 수없는 잘못 디자인 된 응용 프로그램을 중심으로 작업하는 방법 인 것 같습니다.

일부 사람들은 성능 주장이 설득력이 있다고 생각하지만, 저장된 절차가 그렇게 빠르다는 것을 확신시키기 위해 충분한 벤치 마크 데이터를 보지 못했습니다. 모든 사람에게 일화가 있지만 알고리즘이 더 동일하거나 동일하지 않은 나란히 코드가 없습니다.

내가 본 예에서, 오래된 응용 프로그램은 잘못 설계된 엉망이었습니다. 저장된 절차가 작성되면 신청서가 재건되었습니다. 디자인 변경이 플랫폼 변화보다 더 많은 영향을 미쳤다고 생각합니다.

비즈니스 로직은 첫 번째 선택으로 응용 프로그램/중간 단계에 배치해야합니다. 이렇게하면 도메인 모델의 형태로 표현하거나 소스 제어에 배치하거나 관련 코드 (Refactored) 등을 분할하거나 결합 할 수 있습니다. 또한 일부 데이터베이스 공급 업체 독립성을 제공합니다.

객체 지향 언어는 또한 저장된 절차보다 훨씬 표현력이 뛰어나서 코드로 더 쉽게 설명 할 수 있습니다.

저장 프로 시저에 코드를 배치 해야하는 유일한 이유는 다음과 같습니다. 그렇게하면 중요한 성능 혜택을 생성하거나 동일한 비즈니스 코드를 여러 플랫폼 (Java, C#, PHP)으로 실행 해야하는 경우입니다. 여러 플랫폼을 사용하더라도 웹 서비스와 같은 대안이 공유 기능에 더 적합 할 수 있습니다.

내 경험의 대답은 일반적으로 조직의 기술이 위치에 따라 결정되는 다양한 가치에 있습니다.

DBMS는 매우 강력한 짐승이며, 이는 적절하거나 부적절한 치료가 큰 이익이나 큰 위험을 초래할 것임을 의미합니다. 안타깝게도 너무 많은 조직에서는 프로그래밍 직원에게 1 차주의를 기울입니다. DBMS 기술, 특히 쿼리 개발 기술 (행정과 반대로)은 무시됩니다. DBMS 기술을 평가하는 능력도 누락 될 수 있다는 사실에 의해 악화됩니다.

그리고 데이터베이스에 대해 이해하지 못하는 것을 충분히 이해하는 프로그래머는 거의 없습니다.

따라서 활성 레코드 및 LINQ와 같은 차선책 개념의 인기 (명백한 편견을 던지기 위해). 그러나 그들은 아마도 그러한 조직에 가장 적합한 대답 일 것입니다.

그러나 고도의 규모의 조직은 데이터 스토어의 효과적인 사용에 더 많은 관심을 기울이는 경향이 있습니다.

이 질문에 대한 독립형 정답은 없습니다. 그것은 앱의 요구 사항, 개발자의 선호도 및 기술 및 달의 단계에 따라 다릅니다.

비즈니스 로직은 데이터베이스가 아닌 응용 프로그램 계층에 넣어야합니다. 그 이유는 데이터베이스 저장 프로 시저가 항상 사용하는 데이터베이스 제품에 따라 다르기 때문입니다. 이것은 세 단계 모델의 장점 중 하나를 깨뜨립니다. 이 데이터베이스 제품에 대한 추가 저장 절차를 제공하지 않으면 다른 데이터베이스로 쉽게 변경할 수 없습니다. 반면에 때때로 성능 최적화를 위해 저장된 절차에 논리를 넣는 것이 합리적입니다.

내가 말하고 싶은 것은 비즈니스 로직은 응용 프로그램 계층에 넣어야하지만 예외가 있습니다 (주로 성능 이유)

Bussiness 프로그램'레이어'습니다:

1.사용자 인터페이스

이를 구현하는 비즈니스 사용자의 보 h(입/er)작업입니다.그것은 사용하는 용어는 사용자 익숙하다.

2.처리

이것은 어디 계산과 데이터를 조작이 일어난다.어떤 비즈니스 logic 변경과 관련된 데이터는 여기에 구현되어 있다.

3.데이터베이스

다음과 같이 제공할 수 있습니다.정규화하는 순차적인 데이터베이스(표준 SQL 기반의 DBMS s);는 OO-데이터베이스에 저장하는 개체를 감싸는 비즈니스 데이터etc.

어디가

에서 얻을 위한 레이어해야 할 필요한 분석과 디자인이다.이 것을 나타내는 비즈니스 로직 최고의 것을 구현할데이터 무결성 규칙과 동시성/실시간 이슈에 대한 데이터를 업데이트를 일반적으로 구현으로 가까운으로 데이터를,가능한 동일한 것으로 계산 분야,그리고 이것은 좋은 포인터가 저장된 절차/트리거,데이터 무결성 및 거래 통제가 절대로 필요하다.

비즈니스 규칙을 포함하는 의미와 데이터를 사용하는 것이 대부분의 구현에 처리 계층하지만,또한 표시에 사용자 인터페이스로 사용자의 작업 흐름을 연결하는 다양한 프로세스에서 어떤 순서를 반영하는 사용자의 작업이다.

IMHO. 관계형 데이터베이스 중심 앱에서 비즈니스 로직이 어디로 가는지 결정하는 데있어 두 가지 상충되는 우려가 있습니다.

  • 유지 가능성
  • 신뢰할 수 있음

답장. 유지 관리 : 효율적인 미래 개발을 허용하기 위해 비즈니스 로직은 디버깅 및 버전 제어가 가장 쉬운 응용 프로그램의 일부에 속합니다.

답장. 신뢰성 : 불일치의 위험이 심할 때 비즈니스 로직은 데이터베이스 계층에 속합니다. 관계형 데이터베이스는 데이터의 제약 조건을 확인하도록 설계 될 수 있습니다. 예를 들어 특정 열에서 NULL 값을 허용하지 않습니다. 일부 데이터가 특정 상태에 있어야하는 응용 프로그램 설계에서 시나리오가 발생할 때 간단하게 표현하기에는 너무 복잡한 특정 상태에 있어야합니다. 제약 조건, 데이터베이스 계층에서 트리거 또는 유사한 것을 사용하는 것이 합리적 일 수 있습니다.

트리거는 최신 상태를 유지하는 데 어려움을 겪고 있습니다. 특히 클라이언트 시스템에서 앱이 실행될 때 액세스 할 수 없습니다. 그렇다고해서 그들을 추적하거나 업데이트하는 것이 불가능하다는 의미는 아닙니다. 그의 대답에서 S.Lott의 주장은 고통이고 번거 로움이 완전히 유효하다는 것입니다. 그러나 데이터 계층을 처음 설계 할 때 이러한 제한 사항을 염두에두고 관리가 가능한 절대 필수품 이외의 트리거 및 기능을 사용하지 않습니다.

응용 프로그램에서 대부분의 비즈니스 논리는 응용 프로그램의 모델 계층에 포함되어 있으며, 예를 들어 송장은 주어진 판매 주문에서 스스로를 초기화하는 방법을 알고 있습니다. 이와 같은 복잡한 변경 세트에 대해 여러 가지 다른 것들이 순차적으로 수정되면 저장된 절차를 선택하는 대신 일관성을 유지하기 위해 트랜잭션에서 롤업합니다. 총계 등의 계산은 모두 모델 레이어의 메소드로 수행됩니다. 그러나 성능을 위해 무언가를 제거하거나 모든 클라이언트가 사용하는 '변경'테이블에 데이터를 삽입 해야하는 경우 세션 캐시에서 만료해야 할 객체를 파악하면 데이터베이스 계층에 트리거/기능을 사용하여 새 행을 삽입합니다. 이 트리거에서 알림 (Postgres Listen/Unklify 물건)을 보냅니다.

매일 수백 명의 고객이 사용하는 약 1 년 동안 분야에 앱을 사용한 후, 우리가 처음부터 시작 해야하는 경우 변경해야 할 유일한 것은 데이터베이스 기능 (또는 저장된 절차, 그러나 귀하의 프로 시저를 만들기위한 시스템을 설계하는 것입니다. 버전 작성 및 업데이트를 염두에두고 업데이트하십시오.

고맙게도, 우리는 스키마 버전을 추적 할 수있는 시스템을 갖추고 있으므로 데이터베이스 기능을 교체하기 위해 그 위에 무언가를 구축했습니다. 우리가 처음부터 교체 할 필요성을 고려한다면 지금 우리에게 시간을 절약했을 것입니다.


물론, RDBMS 영역을 벗어나 Amazon Simpledb 및 Google의 Bigtable과 같은 튜플 스토리지 시스템으로 나아갈 때 모든 것이 바뀝니다. 그러나 그것은 다른 이야기입니다 :)

우리는 저장 절차에 많은 비즈니스 논리를 넣었습니다. 이상적이지는 않지만 종종 성능과 신뢰성 사이의 균형이 좋습니다.

그리고 우리는 에이커의 솔루션과 코드베이스를 통해 검색 할 필요없이 어디에 있는지 알고 있습니다!

확장 성은 또한 데이터베이스 계층보다 중간 또는 앱 계층에서 비즈니스 로직을 퍼내는 데 매우 중요한 요소입니다. 데이터베이션은 데이터베이스에서 또는 데이터베이스에서 반환되지 않는 데이터베이스와 상호 작용하는 것만 이해해야합니다.

나는 모든 것이 어떤 수준에서 비즈니스 논리의 일부일 수 있다는 것을 지적한 어딘가에 기사를 읽은 것을 기억합니다. 따라서 질문은 의미가 없습니다.

주어진 예는 화면에 송장의 표시라고 생각합니다. 기한이 기한을 빨간색으로 표시하기로 한 결정은 사업 결정입니다 ...

연속체입니다. IMHO 가장 큰 요인은 속도입니다. 유지 보수, 성능, 확장 성, 보안, 신뢰성 등과 같은 프로그래밍의 훌륭한 세입자를 여전히 준수하면서 가능한 한 빨리이 빨판을 실행할 수있는 방법은 종종 SQL이 무언가를 표현하는 가장 간결한 방법이며 문자열 작업 등을 제외하고는 가장 성능이 가장 높은 곳이지만 CLR Procs가 도움을 줄 수있는 곳입니다. 내 믿음은 당신이 당면한 사업에 가장 적합하다고 느끼는 곳을 자유롭게 뿌리는 것입니다. SQL을 볼 때 바지를 똥을 쓴 응용 프로그램 개발자가 있다면 앱 논리를 사용하도록하십시오. 대형 데이터 세트로 고성능 응용 프로그램을 만들려면 DB에 가능한 한 많은 논리를 넣으십시오. DBA를 발사하고 개발자에게 DEV 데이터베이스에 대한 궁극적 인 자유를 제공하십시오. 직업에 대한 대답이나 최상의 도구는 없습니다. 여러 도구가 있으므로 응용 프로그램의 모든 수준에서 전문가가되며 곧 보증 된 Consise Expressive SQL을 작성하고 다른 시간에 응용 프로그램 계층을 사용하는 데 더 많은 시간을 소비 할 것입니다. 나에게 궁극적으로 코드 줄의 수를 줄이는 것이 단순성으로 이어지는 것입니다. 우리는 단지 2500 줄의 앱 코드와 1000 줄의 SQL 라인을 갖춘 SQL Rich 애플리케이션을 도메인 모델로 변환했습니다.이 도메인 모델은 현재 15500 줄의 앱 코드와 2500 줄의 SQL을 보유하여 이전 SQL Rich App의 일을 달성했습니다. 코드의 6 배 증가를 "단순화"로 정당화 할 수 있다면 바로 앞으로 나아갑니다.

This is a great question! I found this after I had already asked a simliar question, but this is more specific. It came up as a result of a design change decision that I wasn't involved in making.

Basically, what I was told was that If you have millions of rows of data in your database tables, then look at putting business logic into stored procedures and triggers. That is what we are doing right now, converting a java app into stored procedures for maintainability as the java code had become convoluted.

I found this article on: The Business Logic Wars The author also made the million rows in a table argument, which I found interesting. He also added business logic in javascript, which is client side and outside of the business logic tier. I hadn't thought about this before even though I've used javascript for validation for years, to along with server side validation.

My opinion is that you want the business logic in the application/middle tier as a rule of thumb, but don't discount cases where it makes sense to put it into the database.

One last point, there is another group where I'm working presently that is doing massive database work for research and the amount of data they are dealing with is immense. Still, for them they don't have any business logic in the database itself, but keep it in the application/middle tier. For their design, the application/middle tier was the correct place for it, so I wouldn't use the size of tables as the only design consideration.

Business logic is usually embodied by objects, and the various language constructs of encapsulation, inheritance, and and polymorphism. For example, if a banking application is passing around money, there may be a Money type that defines the business elements of what "money" is. This, opposed to using a primitive decimal to represent money. For this reason, well-designed OOP is where the "business logic" lives—not strictly in any layer.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top