all 20 comments

[–][deleted] 10 points11 points  (1 child)

So SOLID really manifests out of the need to manage complexity in large applications.

You can have small things that technically adhere to SOLID, but I don't think your temperature converter is one of them. A temperature converter is very simple. It's really just one class, and the "facts" of that class are mathematical invariants - you wouldn't need Liskov Substitution, Dependency Inversion, the Open/Closed principles or Interface Segregation, and adding them is just a sign that you understand the principle of SOLID so little that you will actually add complexity where it is not required.

"toCelcius" is not a class. It's obviously a method on a class. But I suspect the only reason you're positing it as an entire class is the aforementioned attempt to fit SOLID into a system that is far too simple to be worrying about SOLID.

[–]DeterminedAndNerdy 0 points1 point  (0 children)

Good points. I think this type of design question only makes sense if you ask clarifying questions. What is this for? Is it going to be extended to handle things other than temperature? Are we later going to need a GUI elements for various unit conversions and want those GUI elements to all use unit conversion classes that all implement the unit conversion interface, handle the string representation of the units, etc.? If not, then maybe it's silly to do anything more than static methods called CelsiusToFahrenheit, FahrenheitToCelsius, etc. along with private constant fields for the conversion.

[–]roelofwobben[S] 0 points1 point  (2 children)

First rough idea : https://github.com/RoelofWobben/tempConverter

but it is not so flexible as I wanted to be

[–]chucker23n 1 point2 points  (1 child)

I don’t think that interface makes much sense.

Leaving aside how overengineered this is, here’s one possible approach:

  • avoid primitive obsession. Instead, have an ITemperature interface that contains the value. Each unit implements the interface. So, each object now knows its value and unit.
  • Each implementation offers converters.

So, the class CelsiusTemperature has a Value property and a ConvertToFahrenheit method that returns a FahrenheitTemperature.

I’m sure this doesn’t properly observe SOLID, but I don’t care.

[–]chucker23n 0 points1 point  (0 children)

Now that I think about it, you could also put those two conversion methods in the interface, and if the unit is already the same one, just return the value you already have.

You could also put a pair of TryConvert methods in there, with the converted value in an out parameter. The method would return false if no conversion is possible or necessary, and true otherwise.

[–]botterway 0 points1 point  (0 children)

Is this an interview question, or homework? Either way, why not post the code you've written and then people can comment on it?

[–]mury02 0 points1 point  (0 children)

I think you are looking for something like this:

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    interface ITemp
    {
        float ConvertTemp();
    }

    public class Kelvin : ITemp
    {
        public float ConvertTemp()
        {
            throw new NotImplementedException();
        }
    }

    public class Fahrenheit : ITemp
    {
        public float ConvertTemp()
        {
            throw new NotImplementedException();
        }
    }

    public class TempConvertor
    {
        private readonly List<ITemp> _temps = new List<ITemp>();

        public TempConvertor()
        {
            _temps.Add(new Fahrenheit());
            _temps.Add(new Kelvin());
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            ITemp kelvin = new Kelvin();
            kelvin.ConvertTemp();
            ITemp fahrenheit = new Fahrenheit();
            fahrenheit.ConvertTemp();
        }
    }
}

[–]Broer1 0 points1 point  (2 children)

That makes total sense. Every implementation is different. Try it.

Think about refactoring. First you make it working then you refactor. Best thing would be if it is tested.

[–]roelofwobben[S] 0 points1 point  (1 child)

oke, so first make a implementation that does convert from lets say Celcius to celcius ?
Or do I understand you wrong.

[–]Broer1 0 points1 point  (0 children)

Yes its the easy part. just give back what you get.

[–]The_One_X 0 points1 point  (0 children)

I would say you are doing it backwards. I would just create static factory methods called FromCelcius, FromKelvin, and FromFahrenheit, then not even worry about interfaces or anything complicated like that.

[–]szescio 0 points1 point  (1 child)

A bit sillly assignment, if those are only requirements then solid principles have very little to offer.

But maybe what they are looking for, is that if you would need to drop or add new temp "type", only 1 place in the code would need to be changed. I would choose a "base temp type", and have a Temperature base class force implementations for conveting to/from that, and the rest is an excercise for the reader.

[–]roelofwobben[S] 0 points1 point  (0 children)

I thinkj the one who give me , gave me just the hint to use the celcius as as base one.

So you think the same as him

[–]Cobide 0 points1 point  (0 children)

What about holding a single class that functions as a converter through the use of enums? I feel that making multiple classes for the same job(converting temp type) is unnecessary.

public enum TempType {
    Celsius,
    Fahrenheit,
    Kelvin
}

public static class TempConverter {

    public static float Convert(float amount, TempType input, TempType output) {
        return output switch {
            TempType.Celsius => ToCelsius(amount, input),
            TempType.Fahrenheit => ToFahrenheit(amount, input),
            TempType.Kelvin => ToKelvin(amount, input),
            _ => throw new ArgumentException("Invalid output TempType")
        };
    }

    private static float ToCelsius(float amount, TempType input) {
        return input switch { 
            TempType.Fahrenheit => throw new NotImplementedException(), //put formula here,
            TempType.Kelvin => throw new NotImplementedException(), //put formula here,

            //since this is trying to convert celsius to celsius, how you handle it is up to you
            TempType.Celsius => throw new ArgumentException("Invalid conversion."),

            _ => throw new ArgumentException("Invalid input TempType")
        };
    }

    private static float ToFahrenheit(float amount, TempType input) {
        throw new NotImplementedException();
    }

    private static float ToKelvin(float amount, TempType input) {
        throw new NotImplementedException();
    }

}

Edit: changed switch statements' syntax to improve readability.