jeudi 23 septembre 2021

Advice on refactoring lots of consecutive if checks

I have some code like so:

export async function handleRefresh() {
    if (!existsSync('postr.toml')) fail('not a postr directory');

    const posts = expandGlob('posts/*');

    for await (const post of posts) {
        if (!post.isDirectory) {
            console.warn('warning: non-folder found in posts directory');
            continue;
        }

        let {parsedFrontMatter, contents} = extractFrontMatter(await read(post.path + '/post.md'));
        const adapters = parsedFrontMatter.adapters ?? [];

        if (!parsedFrontMatter) {
            fail('no frontmatter for ' + post.path);
            continue;
        }

        if (!Array.isArray(adapters)) {
            fail('adapters is not an array');
            continue;
        }

        if (isValidFrontMatter(parsedFrontMatter)) {
            fail('frontmatter is not valid');
            continue;
        }

        adapters.forEach(async (adapter: string) => {
            const adapterPlugins = parseToml(await read('postr.toml')).adapterPlugins ?? {};

            if (!isObject(adapterPlugins)) {
                fail('adapterPlugins in the configuration is not an object');
                return;
            }

            const adapterPath = adapterPlugins[adapter];

            if (!adapterPath) {
                console.warn('warn: an adapter was set' +
                    'but the corresponding plugin was not configured in `postr.toml`. Skipping');
                return;
            }

            if (!('path' in <any>adapterPath)) {
                fail(`adapter ${adapter} does not have a path`);
                return;
            }

            import((<any>adapterPath).path)
                .then(async module => {
                    const action = getActionForPost(parsedFrontMatter);

                    if (module[action]) {
                        await module[action](contents, parsedFrontMatter, (<any>adapterPath).config, {
                            updateFrontMatter(newData: {[x: string]: any}) {
                                parsedFrontMatter = Object.assign(parsedFrontMatter, newData);
                            },
                            mapID(remote: string | number) {
                                addMapping(parsedFrontMatter.id as string, remote.toString(), adapter);
                            }
                        })
                    } else {
                        console.warn(`Adapter ${adapter} does not support action \`${action}\``);
                        return;
                    }

                    writeFinalContents(parsedFrontMatter, contents, post.path)
                })
                .catch(error => fail(`could not run adapter because of ${error.name}: ${error.message}`));

        });
    }
}

Huge function.

There are a lot of these necessary if checks. 3/4 of the function is if checks, you could say. I want some advice on how I could refactor these statements.

As you can see the checks are not always the same, there are some different checks going on there.

EDIT: I've added real code.

Aucun commentaire:

Enregistrer un commentaire