Repository: typeorm/typeorm
File: src/schema-builder/RdbmsSchemaBuilder.ts (TypeScript)

Code before:
                return this.getTablePath(view) === this.getTablePath(metadata);
            });
            if(viewMetadata){
                viewToMetadata.set(view, viewMetadata);
            }
        }
        // Gather all changed view, that need a drop
        for (const view of this.queryRunner.loadedViews) {
            const viewMetadata = viewToMetadata.get(view);
            if(!viewMetadata){
                continue;
            }
            const viewExpression = typeof view.expression === "string" ? view.expression.trim() : view.expression(this.connection).getQuery();
            const metadataExpression = typeof viewMetadata.expression === "string" ? viewMetadata.expression.trim() : viewMetadata.expression!(this.connection).getQuery();

            if (viewExpression === metadataExpression)
                continue;

            this.connection.logger.logSchemaBuild(`dropping an old view: ${view.name}`);

            // drop an old view
            //await this.queryRunner.dropView(view);
            droppedViews.push(view);
        }
        const viewDependencyChain = (view: View): View[] => {
            const viewMetadata = viewToMetadata.get(view);
            let views = [view];
            if(!viewMetadata){
                return views;
            }
            for(const [view, metadata] of viewToMetadata.entries()){
                if(metadata.dependsOn && (
                    metadata.dependsOn.has(viewMetadata.target) ||
                    metadata.dependsOn.has(viewMetadata.name)
                )){
                    views = views.concat(viewDependencyChain(view));
                }
            }
            return views;
        };
        // Add dependencies to be dropped also
        const droppedViewsWithDependencies: Set<View> = new Set(
            droppedViews.map(view => viewDependencyChain(view))
            .reduce((all, segment) => {
                for(const el of segment){
                    if(!all.includes(el)){
                        all.push(el);
                    }
                }
                return all;
            }, [])

Review comment (refactor):
Everything looks good, beside one small fact that code become a bit complex to review and understand, and it means worse for future maintenance. Can it be refactored to make it more simple and understandable? 

Code after:
                return this.getTablePath(view) === this.getTablePath(metadata);
            });
            if(viewMetadata){
                viewToMetadata.set(view, viewMetadata);
            }
        }
        // Gather all changed view, that need a drop
        for (const view of this.queryRunner.loadedViews) {
            const viewMetadata = viewToMetadata.get(view);
            if(!viewMetadata){
                continue;
            }
            const viewExpression = typeof view.expression === "string" ? view.expression.trim() : view.expression(this.connection).getQuery();
            const metadataExpression = typeof viewMetadata.expression === "string" ? viewMetadata.expression.trim() : viewMetadata.expression!(this.connection).getQuery();

            if (viewExpression === metadataExpression)
                continue;

            this.connection.logger.logSchemaBuild(`dropping an old view: ${view.name}`);

            // Collect view to be dropped
            droppedViews.push(view);
        }

        // Helper function that for a given view, will recursively return list of the view and all views that depend on it
        const viewDependencyChain = (view: View): View[] => {
            // Get the view metadata
            const viewMetadata = viewToMetadata.get(view);
            let viewWithDependencies = [view];
            // If no metadata is known for the view, simply return the view itself
            if(!viewMetadata){
                return viewWithDependencies;
            }
            // Iterate over all known views
            for(const [currentView, currentMetadata] of viewToMetadata.entries()){
                // Ignore self reference
                if(currentView === view) {
                    continue;
                }
                // If the currently iterated view depends on the passed in view
                if(currentMetadata.dependsOn && (
                    currentMetadata.dependsOn.has(viewMetadata.target) ||
                    currentMetadata.dependsOn.has(viewMetadata.name)
                )){
                    // Recursively add currently iterate view and its dependents
                    viewWithDependencies = viewWithDependencies.concat(viewDependencyChain(currentView));
                }
            }
            // Return all collected views
            return viewWithDependencies;
        };