nlkl / Optional

A robust option type for C#
MIT License
903 stars 73 forks source link

Either verbosity #50

Open savpek opened 6 years ago

savpek commented 6 years ago

I am testing this library with one project, however either type seems insanely verbose. Heres my code

        public Option<IEnumerable<ImageEvent>, AggregateException> UpdateK8sDeployments (string newImageUri)
        {
            var parsedUri = ImageUriParser.ParseUri (newImageUri);

            var result = _shell.Run ("kubectl get deployments --all-namespaces -o json")
                .Match<Option<IEnumerable<ImageRow>, Exception>> (
                    success =>
                    {
                        var asJObject = JObject.Parse (success);

                        return ParseImageRowsFromJsonResponse (asJObject)
                            .Where (image => SelectOnlyMatchingDeployments (image, parsedUri))
                            .Some<IEnumerable<ImageRow>, Exception> ();

                    }, error => Option.None<IEnumerable<ImageRow>, Exception> (error))
                .Match<Option<IEnumerable<ImageEvent>, AggregateException>> (images =>
                    {
                        var setResult = images
                            .Select (image =>
                                RunSetNewImageCommand (parsedUri, image));

                        if (setResult.Exceptions ().Any ())
                            return Option.None<IEnumerable<ImageEvent>, AggregateException> (new AggregateException (setResult.Exceptions ()));

                        return Option.Some<IEnumerable<ImageEvent>, AggregateException> (setResult.Values ());
                    },
                    error => Option.None<IEnumerable<ImageEvent>, AggregateException> (new AggregateException (error)));

            result.Match(
                    some => _logger.LogInformation($"Updated images: {string.Join(",", some.Select(x => x.Image))}"),
                    none => _logger.LogError(none.ToString()));

            return result;
        }

Basically this parses json that kubernetes returns and then runs bunch of other terminal commands based on that information + logging. Usual stuff. Those complex generics however really reduces readability of code so i am asking advice is there other solutions to reduce noise or even refactor this alltogether to get better readibility? Theres some things i dont grasp yet.

There was issue about implicit casting as option which was denied since it creates its own problems. I agree totally with simple Option type, however on either version of it it reduces generic that and that boilerplate greatly. LanguageExt uses that solution with either which is nice, however that library API is kind of mess on other areas.

Another way i figured out could be to use static imports, however that is blocked since generic is given as part of method not type. Eg. Option<T,TE>.Some() vs Option.Some<T,TE>().

Is only thing left to refactor those generic definitions out with helper methods to shorten calls?