2017-10-19 7 views
0

je les interfaces suivantes:Idées pour le code refactoring instruction switch dactylographiée

export interface IListItem { 
    [key: string]: any; 
    id: string; 
    title: string; 
    modified: Date; 
    created: Date; 
    modifiedby: string; 
    createdby: string; 
} 

import {IListItem} from "./IListItem"; 

export interface IAnnouncementListItem extends IListItem { 
    announcementBody: string; 
    expiryDate: Date; 
} 


import {IListItem} from "./IListItem"; 

export interface IDirectoryListItem extends IListItem { 
     firstName: string; 
     lastName: string; 
     mobileNumber: string; 
     internalNumber: string; 
} 


import {IListItem} from "./IListItem"; 

export interface INewsListItem extends IListItem { 
    newsheader: string; 
    newsbody: string; 
    expiryDate: Date; 
} 

Et je l'interface usine suivante:

import { IListItem } from "./models/IListItem"; 
import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http"; 
export interface IFactory { 
    getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[]; 
} 

Et puis je la classe suivante qui implémente cette interface

import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http"; 
import { IWebPartContext } from "@microsoft/sp-webpart-base"; 
import { IListItem} from "./models/IListItem"; 
import { IFactory } from "./IFactory"; 
import { INewsListItem } from "./models/INewsListItem"; 
import { IDirectoryListItem } from "./models/IDirectoryListItem"; 
import { IAnnouncementListItem } from "./models/IAnnouncementListItem"; 

export class ListItemFactory implements IFactory { 
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[] { 
     switch(listName) { 
      case "List": 
       let items: IListItem[]; 
       requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: IListItem[] }> => { 
        return response.json(); 
       }) 
       .then((response: { value: IListItem[] }): void => { 
        items= response.value; 
       }); 
       return items; 
      case "News": 
       let newsitems: INewsListItem[]; 
       requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: INewsListItem[] }> => { 
        return response.json(); 
       }) 
       .then((response: { value: INewsListItem[] }): void => { 
        newsitems= response.value; 
       }); 
       return newsitems; 
      case "Announcements": 
       let announcementitems: IAnnouncementListItem[]; 
       requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: IAnnouncementListItem[] }> => { 
        return response.json(); 
       }) 
       .then((response: { value: IAnnouncementListItem[] }): void => { 
        announcementitems= response.value; 
       }); 
       return announcementitems; 
      case "Directory": 
       let directoryitems: IDirectoryListItem[]; 
       requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`, 
       SPHttpClient.configurations.v1, 
       { 
        headers: { 
         "Accept": "application/json;odata=nometadata", 
         "odata-version": "" 
        } 
       }) 
       .then((response: SPHttpClientResponse): Promise<{ value: IDirectoryListItem[] }> => { 
        return response.json(); 
       }) 
       .then((response: { value: IDirectoryListItem[] }): void => { 
        items= response.value; 
       }); 
       return directoryitems; 
      default: 
       return null; 
     } 
     } 
} 

Cette dernière partie est celle que je n'aime pas, j'ai créé un switch stateme nt car en fonction de la liste sélectionnée, le tableau de retour sera de type différent, IListItem, IAnnouncementListItem, IDirectoryListItem ou INewsListItem. Toute suggestion pour raccourcir cette méthode>?

2ème. J'appelle cela de mon composant réagit comme ceci:

// read items using factory method pattern and sets state accordingly 
    private readItemsAndSetStatus(): void { 
    this.setState({ 
     status: "Loading all items..." 
    }); 

    const factory: ListItemFactory = new ListItemFactory(); 
    const items: IListItem[] = factory.getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName); 
    const keyPart: string = this.props.listName === "Items" ? "" : this.props.listName; 

    // the explicit specification of the type argument `keyof {}` is bad and 
    // it should not be required. 
    this.setState<keyof {}>({ 
     status: `Successfully loaded ${items.length} items`, 
     ["Details" + keyPart + "ListItemState"] : { 
      items, 
      columns: [ 
      ] 
     } 
     }); 
    } 

Mais comme vous pouvez voir les getitems retourne un tableau de ListItems, peut-il être amélioré?

Répondre

1

Utilisons cet exemple analogique pour montrer quelques techniques ...

class Example { 
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[] { 
     return []; 
    } 
} 

const example = new Example(); 

// IListItem[] 
const news = example.getItems(null, '', 'News'); 

// IListItem[] 
const announcements = example.getItems(null, '', 'Announcements'); 

Surcharges

Vous pourriez Reprenez types plus spécifiques à l'aide de surcharges de méthode avec les signatures spécialisées:

class Example { 
    public getItems(requester: SPHttpClient, siteUrl: string, listName: 'News'): INewsListItem[]; 
    public getItems(requester: SPHttpClient, siteUrl: string, listName: 'Announcements'): IAnnouncementListItem[]; 
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[]; 
    public getItems(requester: SPHttpClient, siteUrl: string, listName: string): IListItem[] { 
     return []; 
    } 
} 

const example = new Example(); 

// INewsListItem[] 
const news = example.getItems(null, '', 'News'); 

// IAnnouncementListItem[] 
const announcements = example.getItems(null, '', 'Announcements'); 

Modèle de stratégie

Au lieu d'avoir le code pour t il énumère au sein de votre déclaration grand interrupteur, vous pouvez sortir les classes et choisir celui qui convient ...

class ListItemProvider { 
    public getItems(requester: SPHttpClient, siteUrl: string): IListItem[] { 
     // Just the code for list items 
     return []; 
    } 
} 

class NewsItemProvider { 
    public getItems(requester: SPHttpClient, siteUrl: string): INewsListItem[] { 
     // Just the code for news items 
     return []; 
    } 
} 

class AnnouncementItemProvider { 
    public getItems(requester: SPHttpClient, siteUrl: string): IAnnouncementListItem[] { 
     // Just the code for announcment items 
     return []; 
    } 
} 


class Example { 
    public getItemProvider(listName: 'News'): NewsItemProvider; 
    public getItemProvider(listName: 'Announcments'): AnnouncementItemProvider; 
    public getItemProvider(listName: 'List' | 'News' | 'Announcments'): ListItemProvider; 
    public getItemProvider(listName: 'List' | 'News' | 'Announcments') : ListItemProvider { 
     switch (listName) { 
      case 'List': 
       return new ListItemProvider(); 
      case 'News': 
       return new NewsItemProvider(); 
      case 'Announcments': 
       return new AnnouncementItemProvider(); 
      default: 
       throw new Error('No provider for ' + listName); 
     } 
    } 
} 

const example = new Example(); 

// INewsListItem[] 
const news = example.getItemProvider('News').getItems(null, ''); 

// IAnnouncementListItem[] 
const announcements = example.getItemProvider('Announcments').getItems(null, ''); 

Vous pouvez ensuite extraire le code commun dans une classe de base. Chaque partie du code est plus petite et plus facile à lire. Il y a quelques parties de plus, mais elles séparent logiquement les choses.

Il existe d'autres moyens de parvenir à vos fins, mais ils vous guideront dans la bonne direction.