473,405 Members | 2,310 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Versions

Hi,

Appreciate some input on a small design issue. Need to represent a
version in an application that come in various formats (1.2.3 or 'a')
and number of octets (1.2 or 1.2.3.4.5).

Considering using an interface as shown below with two implementations
(for now). Lets for simplicity call them VersionNumber and
VersionCharacter.

interface IVersion : IComparable<IVersion>
{

}

Comparing two instances of the same implementation is fairly
straightforward (i.e. compare VersionNumber with VersionNumber).
However comparing a VersionNumber instance with a VersionCharacter is
more difficult IMHO. How do I specify which is greater and how do I
model that? Obviously a third implementation could also appear at some
point. Should such a decision be dealt with internally in each class,
for instance VersionNumber is always greater than another IVersion
type. Then you can get inconsistencies if VersionCharacter has the
opposite rule. So I was thinking about having a central method for
this specific sort of decision but must admit I'm uncertain at this
point. Any other way of solving the issue would be interesting.

Hope I explained the problem properly. If you see any other problems
with the design I’m all ears.

The goal is to have a flexible and maintainable implementation (maybe
asking too much).
Aug 15 '08 #1
8 1363
On Aug 15, 5:18*pm, RedLars <Liverpool1...@gmail.comwrote:
Hi,

Appreciate some input on a small design issue. Need to represent a
version in an application that come in various formats (1.2.3 or 'a')
and number of octets (1.2 or 1.2.3.4.5).

Considering using an interface as shown below with two implementations
(for now). Lets for simplicity call them VersionNumber and
VersionCharacter.

interface IVersion : IComparable<IVersion>
{

}

Comparing two instances of the same implementation is fairly
straightforward (i.e. compare VersionNumber with VersionNumber).
However comparing a VersionNumber instance with a VersionCharacter is
more difficult IMHO. How do I specify which is greater and how do I
model that?
I would say that compare operation is not common to all versions, but
specific to every version subtype (i.e., the interface should reflect
the fact that you cannot compare versions of two different types). If
you want to capture this requirement in an interface, it is possible
to do so by splitting it in two parts like this:

interface IVersion { /* truly universal methods */ }
interface IVersion<TVersion: IVersion, IComparable<IVersion>
{ ... }
class VersionNumber : IVersion<VersionNumber{ ... }
class VersionCharacter : IVersion<VersionCharacter{ ... }

This still lets you to retain the genericity where it is typesafe to
do so. For example, a metod that takes two version numbers, and at
some point needs to compare them against each other, but otherwise
doesn't care about their specific types, could be declared like this:

void Foo<T>(IVersion<Tv1, IVersion<Tv2)
{
// call various IVersion members on v1 and v2
...
if (v1.CompareTo(v2) == 0) { ... }
}
Aug 15 '08 #2
On 15 Aug, 15:25, Pavel Minaev <int...@gmail.comwrote:
On Aug 15, 5:18*pm, RedLars <Liverpool1...@gmail.comwrote:
Hi,
Appreciate some input on a small design issue. Need to represent a
version in an application that come in various formats (1.2.3 or 'a')
and number of octets (1.2 or 1.2.3.4.5).
Considering using an interface as shown below with two implementations
(for now). Lets for simplicity call them VersionNumber and
VersionCharacter.
interface IVersion : IComparable<IVersion>
{
}
Comparing two instances of the same implementation is fairly
straightforward (i.e. compare VersionNumber with VersionNumber).
However comparing a VersionNumber instance with a VersionCharacter is
more difficult IMHO. How do I specify which is greater and how do I
model that?

I would say that compare operation is not common to all versions, but
specific to every version subtype (i.e., the interface should reflect
the fact that you cannot compare versions of two different types). If
you want to capture this requirement in an interface, it is possible
to do so by splitting it in two parts like this:

* interface IVersion { /* truly universal methods */ }
* interface IVersion<TVersion: IVersion, IComparable<IVersion>
{ ... }
* class VersionNumber : IVersion<VersionNumber{ ... }
* class VersionCharacter : IVersion<VersionCharacter{ ... }

This still lets you to retain the genericity where it is typesafe to
do so. For example, a metod that takes two version numbers, and at
some point needs to compare them against each other, but otherwise
doesn't care about their specific types, could be declared like this:

* void Foo<T>(IVersion<Tv1, IVersion<Tv2)
* {
* * // call various IVersion members on v1 and v2
* * ...
* * if (v1.CompareTo(v2) == 0) { ... }
* }
Thanks for you quick response.

At our company the version syntax has changed over time, so an old
driver might have version 'F' at one point and then skip to version
2.0.0, but this is again different from one product to another. To
cover such case it would be very handy to be able to compare different
IVersion types. Your example would not cover such a case. Maybe I'm
trying to implement too much logic into a simple interface.
Aug 15 '08 #3
"RedLars" <Li***********@gmail.comwrote:
At our company the version syntax has changed over time, so an old driver
might have version 'F' at one point and then skip to version 2.0.0, but
this is again different from one product to another.
Then the things you are comparing are "ProductVersions", not Versions. It
does not make sense to compare the versions of two different products if one
might have conceivably gone 1, 2, F, 3, G and the other might have gone 1,
F, 2, G, 3.

Eq.
Aug 15 '08 #4
On 15 Aug, 16:35, "Paul E Collins" <find_my_real_addr...@CL4.org>
wrote:
"RedLars" <Liverpool1...@gmail.comwrote:
At our company the version syntax has changed over time, so an old driver
might have version 'F' at one point and then skip to version 2.0.0, but
this is again different from one product to another.

Then the things you are comparing are "ProductVersions", not Versions. It
does not make sense to compare the versions of two different products if one
might have conceivably gone 1, 2, F, 3, G and the other might have gone 1,
F, 2, G, 3.

Eq.
Any version within our company has only had one change in syntax. So a
typical version history could be A, B, C, D, 2.0.0.0, 2.1.0.0,
3.1.0.0. etc.

Obviously a version could change to a third syntax but I highly doubt
it will ever alternate between syntaxes as shown in your response.

So you might end-up in a scenario where you want to compare A with
3.1.0.0 for a certain piece of equipment. In this case 3.1.0.0 would
be greater.

Hope you understand my requirement.

Cheers
Aug 15 '08 #5
Hi Lars,

Lets assume both of the following classes implement IVersion

CVersionTypeAlpha -- class for alpha comparation (A,B)
CVersionTypeNumeric -- (1.2.x, 2.0.x)

So the base rule is .. Alpha older that Numeric. Right?

So make a special check in the Compare methods for this rule. If the 2
parameters of the Compare method are different types, then is Alpha older
the Numeric.

Another way is via a mapping, where the CVersionTypeAlpha class converts all
of its versions to 0.0.0.x, where x is the ordinal value of the character.
E.g. Version "A" is converted to "0.0.0.65". Of course this assumes, that no
version "0.0.0.x" exists and that AlphaVersions are older than
NumericVersions. Its also assumed, that "A" is older that "a". But you can
make it case-in-sensitive. You can also add/subract an offset from the
ordinal value. This really depends on the already used version numbers and
version patterns. But if you can map it to this standard format, then you
are able to do just a CVersionTypeNumeric compare at the end.

Till now i have not read, how you decide what version class you have to
instantiate. I assume you have this already implemented and solved.

Your goal was to get a flexible and maintainable implementation. The problem
is: when the version numbers of your projects are not standardized or follow
different rules, you'll never get a standard implementation for all cases.
You need to implement special cases to deal with it.

-J-
Aug 15 '08 #6
On 15 Aug, 17:40, "Luthgers, John" <jl...@gmx.net.nospamwrote:
Hi Lars,

Lets assume both of the following classes implement IVersion

CVersionTypeAlpha -- class for alpha comparation (A,B)
CVersionTypeNumeric -- (1.2.x, 2.0.x)

So the base rule is .. Alpha older that *Numeric. Right?

So make a special check in the Compare methods for this rule. If the 2
parameters of the Compare method are different types, then is Alpha older
the Numeric.

Another way is via a mapping, where the CVersionTypeAlpha class converts all
of its versions to 0.0.0.x, where x is the ordinal value of the character..
E.g. Version "A" is converted to "0.0.0.65". Of course this assumes, thatno
version "0.0.0.x" exists and that AlphaVersions are older than
NumericVersions. Its also assumed, that "A" is older that "a". But you can
make it case-in-sensitive. You can also add/subract an offset from the
ordinal value. This really depends on the already used version numbers and
version patterns. But if you can map it to this standard format, then you
are able to do just a CVersionTypeNumeric compare at the end.

Till now i have not read, how you decide what version class you have to
instantiate. I assume you have this already implemented and solved.

Your goal was to get a flexible and maintainable implementation. The problem
is: when the version numbers of your projects are not standardized or follow
different rules, you'll never get a standard implementation for all cases..
You need to implement special cases to deal with it.

-J-
Thanks for your input John.

Your last paragraph is spot on. The requirements are a bit non-
standardized. If I wanted to implement both a standardized and a non-
standardized implementation with as little duplicate code as possible
how would I accomplish this?

Say for instance
interface IVersion { /* standardized interface */ }
interface IVersionProprietary { /* non-standardized interface */ }

However this leads to multiple implementations for each interface with
very little difference between them (duplicated code).

As for instantiate the objects I´m considering using a factory that
analysis the string version input and returns the appropriate
interface implementation.
Aug 16 '08 #7
I would not add a second interface, because the goal is easy handling of
different versions and that means it should be handled by one interface. But
I wouldn't use interfaces at all. Here is my solution, but it supports only
versions like "A", "B", "C", "1.0.2", "2.0.0.1"... and ofcourse you could
add a interface like IVersion. But at the end you'll need a factory class,
that can create a instance of this interface, and so i decided the left it
out.

The example gives you the ability to create a version object
(CreateObjectFromString) without to know what type of version you have,
compare to version-object by using "if (ver1 < ver2) ..." and has also a
IComparable implementation to get a list sorted correctly.

Simply paste the following code to a program.cs file. It takes me just a few
minutes, so i hope i've done all things right. I used VS2005 for this... and
maybe it suit your needs.

-J-

<code>
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace VersionChecker
{
public class CVersion : IComparable<CVersion>
{
string version;

protected CVersion() { }

public static CVersion CreateObjectFromString(string version)
{
if (String.IsNullOrEmpty(version)) { throw new ArgumentException(); }
if (version.Length == 1 && version[0] >= 'A' && version[0] <= 'Z')
{
return new CVersionAlpha(version);
}
else
{
return new CVersionNumeric(version);
}
}
public string Version
{
get { return version; }
set { version = value; }
}

public static bool operator <(CVersion left, CVersion right)
{
if (left is CVersionAlpha && right is CVersionNumeric) { return true; }
if (left is CVersionNumeric && right is CVersionAlpha) { return false; }
return left.Version.CompareTo(right.Version) < 0;
}
public static bool operator >(CVersion left, CVersion right)
{
if (left is CVersionAlpha && right is CVersionNumeric) { return false; }
if (left is CVersionNumeric && right is CVersionAlpha) { return true; }
return left.Version.CompareTo(right.Version) 0;
}
public static bool operator ==(CVersion left, CVersion right)
{
return left.Version.CompareTo(right.Version) == 0;
}
public static bool operator !=(CVersion left, CVersion right)
{
return left.Version.CompareTo(right.Version) != 0;
}

#region IComparable<CVersionMembers

public int CompareTo(CVersion other)
{
if (this is CVersionAlpha && other is CVersionNumeric) { return -1; }
if (this is CVersionNumeric && other is CVersionAlpha) { return 1; }
return this.Version.CompareTo(other.Version);
}

#endregion
}

public class CVersionAlpha : CVersion
{
public CVersionAlpha(string ver)
{
Version = ver;
}
}
public class CVersionNumeric : CVersion
{
public CVersionNumeric(string ver)
{
Version = ver;
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] argv)
{
CVersion c0 = CVersion.CreateObjectFromString("A"); Debug.WriteLine("c0 =
" + c0.Version);
CVersion c1 = CVersion.CreateObjectFromString("C"); Debug.WriteLine("c1 =
" + c1.Version);
CVersion c2 = CVersion.CreateObjectFromString("1.0.1");
Debug.WriteLine("c2 = " + c2.Version);
CVersion c3 = CVersion.CreateObjectFromString("2.0.1");
Debug.WriteLine("c3 = " + c3.Version);

SortedList<CVersion, objectlist = new SortedList<CVersion, object>();
list.Add(c3, null);
list.Add(c2, null);
list.Add(c1, null);
list.Add(c0, null);

foreach (CVersion ver in list.Keys)
{
Debug.WriteLine(ver.Version);
}

// now the tests
if (c0 < c1) { Debug.WriteLine("c0 older than c1"); }
if (c0 c1) { Debug.WriteLine("c0 newer then c1"); }
if (c0 == c1) { Debug.WriteLine("c0 is equal c1"); }
if (c0 != c1) { Debug.WriteLine("c0 is not equal c1"); }

if (c0 < c2) { Debug.WriteLine("c0 older than c2"); }
if (c0 c2) { Debug.WriteLine("c0 newer then c2"); }
if (c0 == c2) { Debug.WriteLine("c0 is equal c2"); }
if (c0 != c2) { Debug.WriteLine("c0 is not equal c2"); }

if (c3 < c1) { Debug.WriteLine("c3 older than c1"); }
if (c3 c1) { Debug.WriteLine("c3 newer then c1"); }
if (c3 == c1) { Debug.WriteLine("c3 is equal c1"); }
if (c3 != c1) { Debug.WriteLine("c3 is not equal c1"); }

if (c2 < c3) { Debug.WriteLine("c2 older than c3"); }
if (c2 c3) { Debug.WriteLine("c2 newer then c3"); }
if (c2 == c3) { Debug.WriteLine("c2 is equal c3"); }
if (c2 != c3) { Debug.WriteLine("c2 is not equal c3"); }
}
}
}
</code>
Aug 16 '08 #8
On 16 Aug, 13:02, "Luthgers, John" <jl...@gmx.net.nospamwrote:
I would not add a second interface, because the goal is easy handling of
different versions and that means it should be handled by one interface. But
I wouldn't use interfaces at all. Here is my solution, but it supports only
versions like "A", "B", "C", "1.0.2", "2.0.0.1"... and ofcourse you could
add a interface like IVersion. But at the end you'll need a factory class,
that can create a instance of this interface, and so i decided the left it
out.

The example gives you the ability to create aversionobject
(CreateObjectFromString) without to know what type ofversionyou have,
compare toversion-object by using "if (ver1 < ver2) ..." and has also a
IComparable implementation to get a list sorted correctly.

Simply paste the following code to a program.cs file. It takes me just a few
minutes, so i hope i've done all things right. I used VS2005 for this... and
maybe it suit your needs.

-J-

<code>
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace VersionChecker
{
*public class CVersion : IComparable<CVersion>
*{
* stringversion;

* protected CVersion() { }

* public static CVersion CreateObjectFromString(stringversion)
* {
* *if (String.IsNullOrEmpty(version)) { throw new ArgumentException(); }
* *if (version.Length == 1 &&version[0] >= 'A' &&version[0] <= 'Z')
* *{
* * return new CVersionAlpha(version);
* *}
* *else
* *{
* * return new CVersionNumeric(version);
* *}
* }
* public stringVersion
* {
* *get { returnversion; }
* *set {version= value; }
* }

* public static bool operator <(CVersion left, CVersion right)
* {
* *if (left is CVersionAlpha && right is CVersionNumeric) { return true; }
* *if (left is CVersionNumeric && right is CVersionAlpha) { return false; }
* *return left.Version.CompareTo(right.Version) < 0;
* }
* public static bool operator >(CVersion left, CVersion right)
* {
* *if (left is CVersionAlpha && right is CVersionNumeric) { return false; }
* *if (left is CVersionNumeric && right is CVersionAlpha) { return true; }
* *return left.Version.CompareTo(right.Version) 0;
* }
* public static bool operator ==(CVersion left, CVersion right)
* {
* *return left.Version.CompareTo(right.Version) == 0;
* }
* public static bool operator !=(CVersion left, CVersion right)
* {
* *return left.Version.CompareTo(right.Version) != 0;
* }

* #region IComparable<CVersionMembers

* public int CompareTo(CVersion other)
* {
* *if (this is CVersionAlpha && other is CVersionNumeric) { return -1; }
* *if (this is CVersionNumeric && other is CVersionAlpha) { return 1;}
* *return this.Version.CompareTo(other.Version);
* }

* #endregion
*}

*public class CVersionAlpha : CVersion
*{
* public CVersionAlpha(string ver)
* {
* *Version= ver;
* }
*}
*public class CVersionNumeric : CVersion
*{
* public CVersionNumeric(string ver)
* {
* *Version= ver;
* }
*}

*static class Program
*{
* /// <summary>
* /// The main entry point for the application.
* /// </summary>
* [STAThread]
* static void Main(string[] argv)
* {
* *CVersion c0 = CVersion.CreateObjectFromString("A"); Debug.WriteLine("c0 =
" + c0.Version);
* *CVersion c1 = CVersion.CreateObjectFromString("C"); Debug.WriteLine("c1 =
" + c1.Version);
* *CVersion c2 = CVersion.CreateObjectFromString("1.0.1");
Debug.WriteLine("c2 = " + c2.Version);
* *CVersion c3 = CVersion.CreateObjectFromString("2.0.1");
Debug.WriteLine("c3 = " + c3.Version);

* *SortedList<CVersion, objectlist = new SortedList<CVersion, object>();
* *list.Add(c3, null);
* *list.Add(c2, null);
* *list.Add(c1, null);
* *list.Add(c0, null);

* *foreach (CVersion ver in list.Keys)
* *{
* * Debug.WriteLine(ver.Version);
* *}

* *// now the tests
* *if (c0 < c1) { Debug.WriteLine("c0 older than c1"); }
* *if (c0 c1) { Debug.WriteLine("c0 newer then c1"); }
* *if (c0 == c1) { Debug.WriteLine("c0 is equal c1"); }
* *if (c0 != c1) { Debug.WriteLine("c0 is not equal c1"); }

* *if (c0 < c2) { Debug.WriteLine("c0 older than c2"); }
* *if (c0 c2) { Debug.WriteLine("c0 newer then c2"); }
* *if (c0 == c2) { Debug.WriteLine("c0 is equal c2"); }
* *if (c0 != c2) { Debug.WriteLine("c0 is not equal c2"); }

* *if (c3 < c1) { Debug.WriteLine("c3 older than c1"); }
* *if (c3 c1) { Debug.WriteLine("c3 newer then c1"); }
* *if (c3 == c1) { Debug.WriteLine("c3 is equal c1"); }
* *if (c3 != c1) { Debug.WriteLine("c3 is not equal c1"); }

* *if (c2 < c3) { Debug.WriteLine("c2 older than c3"); }
* *if (c2 c3) { Debug.WriteLine("c2 newer then c3"); }
* *if (c2 == c3) { Debug.WriteLine("c2 is equal c3"); }
* *if (c2 != c3) { Debug.WriteLine("c2 is not equal c3"); }
* }
*}}

</code>
Thanks for the feedback.

Appreciate the code snippet but I do not think its entirely correct.
Because the internal verison is represented by string 12.0.0.1 would
be smaller than 2.0.0.1 which is not the case. Also, any particular
reason why you didnt use object.ReferenceEquals in the various
operator methods?

Will probably go with one interface, two implementation and a factory
for creation. Then add the rule inside each implementation that Number
is greater than Alpha.
Aug 18 '08 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Oliver Elphick | last post by:
The attached proposal is written primarily for Debian. Its motivation is that the current package upgrade process is pretty flaky and also that the current packaging does not really provide for...
14
by: wolftor | last post by:
1) Is there a free runtime version of Access available that is more recent than the one for Access 2000? 2) If I create an application (MDE) in A2K, will it run on all later versions of Access?...
4
by: Dalan | last post by:
After reading and experiencing the phenomenon of installing MS Office 2000 on a system that already has MS Office 97, or for that matter just Access 97 Runtime, I saw the ugliness that ensues. If...
5
by: Michael Maes | last post by:
Hi, We have an ERP-Application that needs to interact with an "external accountancy program". This is acchieved through a "Connector" (ActiveX-dll) so kindly provided by the Accountancy-Program....
37
by: Allen Browne | last post by:
If you develop for others, you probably have multiple versions of Access installed so you can edit and create MDEs for clients in different versions. This works fine under Windows XP, even with...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.