jorgevgut / airquality-mx

MIT License
180 stars 74 forks source link

linq #1

Open DavidArcos07 opened 4 years ago

DavidArcos07 commented 4 years ago

Buenas tardes, te dejo otra forma de hacer linq para que tu código quede mas elegante.

`using Latincoder.AirQuality.Model.External;

using System.Linq; using System.Collections.Generic;

namespace Latincoder.AirQuality.Model.DTO { public class CityFeed { private Station _maxAqiStation;

    /* Constructor methods*/
    internal CityFeed() { }

    public CityFeed(List<Station> stations, string cityName)
    {
        Stations = stations;
        CityName = cityName;
        _maxAqiStation = Stations.OrderByDescending(station => station.AQI).FirstOrDefault();
    }

    public static CityFeed From(List<WaqiCityFeed> waqiStations)
    {
        var stations = waqiStations.Select(station => new Station(station.Data.Idx.ToString(),
                            station.Data.Aqi,
                            station.Data.City.Name,
                            station.Data.City.Url,
                            Attribution.ListFrom(station.Data.Attributions)));

        return new CityFeed
        {
            Stations = stations.ToList(),
            CityName = CityFeed.findBestCityName(stations.ToList()),
            _maxAqiStation = stations.OrderByDescending(station => station.AQI).FirstOrDefault()
        };
    }

    /* Properties */
    public string CityName { get; set; }

    // TODO: accessing MaxAqiStation is O(n) - cache result in private field
    public int MaxAQI { get => _maxAqiStation.AQI; }

    public List<Station> Stations { get; set; }

    // TODO: accessing MaxAqiStation is O(n) - cache result in private field
    public Station MaxAqiStation { get => _maxAqiStation; }

    /* 
        internal methods - validations and utilities of this  class
        method which do not required of an instance are static

        TODO: use regex pattern to extract groups from valid Waqi API URI
        This is the known pattern:
        https://aqicn.org/city/:country/:city/:station
        Ex:
        https://aqicn.org/city/mexico/guadalajara/vallarta

    */

    //TODO: requires validation and error handling
    static string[] getCountryCityStationArray(string url)
    {
        var delimiter = @"city/";
        var delimiterIndex = url.IndexOf(delimiter);
        return url.Substring(delimiterIndex).Split('/');
    }

    static string getCityNameFromUrl(string url)
    {
        var countryCityName = getCountryCityStationArray(url);
        return countryCityName.Length > 2 ? countryCityName[2] : string.Empty;
    }

    static string findBestCityName(List<Station> stations)
    {
        var bestStation = stations.OrderByDescending(station => station).FirstOrDefault();
        return getCityNameFromUrl(bestStation.Url);
    }
}

}`

DavidArcos07 commented 4 years ago

Attribution.cs

`using System.Collections.Generic; using System.Linq;

namespace Latincoder.AirQuality.Model.DTO { public class Attribution { public Attribution() {}

    public Attribution(string name = null, string url = null) {
        Name = name;
        Url = url;
    }

    public static Attribution From(Latincoder.AirQuality.Model.External.Attribution attribution) {
        return new Attribution(attribution.Name, attribution.Url);
    }

    public static List<Attribution> ListFrom(
        List<Latincoder.AirQuality.Model.External.Attribution> waqiAttributions) {
        return waqiAttributions.Select(waqiAttribution => Attribution.From(waqiAttribution)).ToList();
    }

    public string Name { get; } = string.Empty;

    public string Url   { get; } = string.Empty;

    public override string ToString() {
        if (string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(Url)) {
            return string.Empty;
        }
        if (string.IsNullOrEmpty(Name) || string.IsNullOrEmpty(Url)) {
            return $"Attr: {Name}${Url}";
        }

        return $"Attr: {Name} - {Url}";
    }
}

}`

jorgevgut commented 4 years ago

Hola @DavidArcos07 muchas gracias por los comments. Estoy al tanto que Linq tiene tanto su query como method syntax, sin embargo no he encontrado referencias todavia que usar method syntax sea preferido sobre el query excepto por preferencias personales de cada quien. Concuerdo contigo en que yo preferiria Method syntax, sin embargo estoy optando por query como preferencia para familiarizarme con este aspecto de los features disponibles para el lenguaje, si tienes algunas referencias que documenten cuando usar method syntax sobre query te lo agradeceria, eso me ayudaria mucho.

En cuanto al IsNullOrEmpty, hay una razon por la cual no lo estoy usando y es porque ese parametro no lo estoy dise;ando para que sea nulo, si por alguna razon llegase a ser nulo, la aplicacion deberia fallar, todavia es muy temprano para que se note y lamentablemente no he tenido tiempo para documentar a ese nivel de detalle, pero tratare de irlo documentando poco a poco. saludos y gracias!