Rockford Lhotka's Blog

Home | Lhotka.net | CSLA .NET

 Tuesday, 09 January 2007

Here's an issue from Windows Forms that appears to have crept into WPF as well – along with a solution (thanks to Sam Bent and Kevin Moore from the WPF team):

 

Consider a class with a property that enforces a business rule - such as that the value must be all upper case:

 

public class Test : INotifyPropertyChanged

{

  public event

    System.ComponentModel.PropertyChangedEventHandler

    PropertyChanged;

  // ...

 

  private string _data;

 

  public string Data

  {

    get

    {

      return _data;

    }

    set

    {

      _data = value.ToUpper();

      OnNotifyPropertyChanged("Data");

     }

  }

}

 

Bind this to a TextBox and type in a lower-case value. The user continues to see the lower-case value on the screen, even though the object obviously has an upper-case value. The PropertyChanged event is blissfully ignored by WPF data binding.

 

I believe this is the same "optimization" as in Windows Forms, where the assumption is that since the value was put into the object by data binding that it can’t be different from what's on the screen - so no refresh is needed. Obviously that is a unfortunate viewpoint, as it totally ignores the idea than an object might be used to centralize business logic or behavior...

 

In Windows Forms the solution to this issue is relatively simple: handle an event from the BindingSource and force the BindingSource to refresh the value. Bill McCarthy wrapped this solution into an extender control, which I included in CSLA .NET, making the workaround relatively painless.

 

In WPF the solution is slightly different, but also relatively painless.

 

It turns out that this optimization doesn’t occur if an IValueConverter is associated with the binding, and if the binding’s UpdateSourceTrigger is not PropertyChanged.

 

For the TextBox control the UpdateSourceTrigger is LostFocus, so it is good by default, but you’ll want to be aware of this property for other control types.

 

An IValueConverter object’s purpose is to format and parse the value as it flows to and from the target control and source data object. In my case however, I don’t want to convert the value at all, I just want to defeat this unfortunate “optimization”. What’s needed is an identity converter: a converter that does no conversion.

 

namespace Csla.Wpf

{

  public class IdentityConverter : IValueConverter

  {

    #region IValueConverter Members

 

    public object Convert(

      object value, Type targetType,

      object parameter, System.Globalization.CultureInfo culture)

    {

      return value;

    }

 

    public object ConvertBack(

      object value, Type targetType,

      object parameter, System.Globalization.CultureInfo culture)

    {

      return value;

    }

 

    #endregion

  }

}

 

Just configure this in your XAML:

 

<Page x:Class="PTWpf.ProjectEdit"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:csla="clr-namespace:Csla.Wpf"

    Title="Project Edit"

    >

  <Page.Resources>

    <csla:IdentityConverter x:Key="IdentityConverter" />

  </Page.Resources>

...

  <TextBox Text="{Binding Data, Converter={StaticResource IdentityConverter}}"></TextBox>

...

 

Just like that, it all works as expected and the value from the object is reflected in the UI.

Tuesday, 09 January 2007 15:08:23 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Wednesday, 03 January 2007

I recently received an email that included this bit:

 

“You are killing me. I wrote a rather scathing review of your Professional Business Objects with C# on Amazon.com and on my own blog. However, recently I read a transcription of an ARCast with Ron Jacobs where you talked about business objects. I believe I agreed with everything you said. What are you trying to do to me?

 

I am just a regular shmoe developer, who preaches when listened to about the joys and benefits of OO design for the common business application. I feel too many develop every application like it is just babysitting a database. Every object’s purpose is for the CRUD of data in a table. I have developed great disdain for companies, development teams, and senior developers who perpetuate this problem. I felt Expert C# 2005 Business Object perpetuates this same kind of design, thus the 3 star rating on Amazon for your book.

 

In the ARCast you mentioned a new book coming out. I am hoping it is the book I have been looking for. If I wrote it myself it would be titled something like, “Business Objects in the Real World.” It would address the problems of data-centric design and how some objects truly are just for managing data and others conduct a business need explained by and expert. These two objects would be pretty different and possibly even use a naming convention to explicitly differentiate the two. For example I don’t want my “true” business objects with getters, setters, isDirty flags or anything else that might make them invalid and popping runtime errors when trying to conduct their business.

 

Anyway, I could ramble on (It’s my nature). However, I just want to drop you a line and say there is a real disconnect between us, but at the same time, I wanted to show everyone at my office what you were saying in your interview. You were backing me up! However, just months ago I was using your writings to explain what is wrong with software development. We seem to be on the same page, or close anyway, but maybe coming to different conclusions. I guess that’s what is bothering me.”

 

The following is my response, which I thought I’d share here on my blog because I ended up rambling on more than I’d planned, and I thought it might be interesting/useful to someone:

 

I would guess that the disconnect may flow from our experiences during our careers - what we've seen work and not work over time.

 

For my part, I've become very pragmatic. The greatest ideas in the world tend to fall flat in real life because people don't get them, or they have too high a complexity or cost barrier to gain their benefit. For a very long time OO itself fit this category. I remember exploring OO concepts in the late 80's and it was all a joke. The costs were ridiculously high, and the benefits entirely theoretical.

 

Get into the mid-90's and components show up, making some elements of OO actually useful in real life. But even then RAD was so powerful that the productivity barrier/differential between OO and RAD was ridiculously high. I spent untold amounts of time and effort trying to reconcile these two to allow the use of OO and RAD both - but with limited success. The tools and technologies simply didn't support both concepts - at least not without writing your own frameworks for everything and ignoring all the pre-existing (and established) RAD tools in existence.

 

Fortunately by this time I'd established both good contacts and a good reputation within key Microsoft product teams. Much of the data binding support in .NET (Windows Forms at least) is influenced by my constant pressure to treat objects as peers to recordset/resultset/dataset constructs. I continue to apply this pressure, because things are still not perfect - and with WPF they have temporarily slid backwards somewhat. But I know people on that team too, and I think they'll improve things as time goes on.

 

In the meantime Java popularizes the idea of ORM - but solutions exist for only the most basic scenarios - mapping table data into entity objects. While they claim to address the impedance mismatch problem, they really don't, because they aren't mapping into real OO designs, but rather into data-centric object models. Your disdain for today’s ORM tools must be boundless J

 

For better or worse, Microsoft is following that lead in the next version of ADO.NET - and I don't totally blame them; a real solution is complex enough that it is hard to envision, much less implement. However, here too I hold out hope, because the current crop of "ORM" tools are starting to create nice enough entity objects that it may become possible to envision a tool that maps from entity objects to OO objects using a metadata scheme between the two. This is an area I've been spending some time on of late, and I think there's some good potential here.

 

Through all this, I've been working primarily with mainstream developers (“Mort”). Developers who do this as a job, not as an all-consuming passion. Developers who want to go home to their families, their softball games, their real lives. Who don't want to master "patterns" and "philosophies" like Agile or TDD; but rather they just want to do their job with a set of tools that help them do the right thing.

 

I embrace that. This makes me diametrically opposed to the worldviews of a number of my peers who would prefer that the tools do less, so as to raise the bar and drive the mainstream developers out of the industry entirely. But that, imo, is silly. I want mainstream developers to have access to frameworks and tools that help guide them toward doing the right thing - even if they don't take the time to understand the philosophy and patterns at work behind the scenes.

 

I don't remember when I did the ARCast interview, but I was either referring to the 2005 editions of my business objects books which came out in April/May, or to the ebook I'm finishing now, which covers version 2.1 of my CSLA .NET framework. Odds are it is the former, and it isn't the book you are looking for - though you might enjoy Chapter 6.

 

In general I think you can take a couple approaches to thinking about objects.

 

One approach, and I think the right one, is to realize that all objects are behavior-driven and have a single responsibility. Sometimes that responsibility is to merely act as a data container (DTO or entity object). Other times it is to act as a rich binding source that implements validation, authorization and other behaviors necessary to enable the use of RAD tools. Yet other times it is to implement pure, non-interactive business behavior (though this last area is being partially overrun by workflow technologies like WF).

 

Another way to think about objects is to say there are different kinds of object, with different design techniques for each. So entity objects are designed quasi-relationally, process objects are designed somewhat like a workflow, etc. I personally think this is a false abstraction that misses the underlying truth, which is that all objects must be designed around responsibility and behavior as they fit into a use case and architecture.

 

But sticking with the pure responsibility/behavior concept, CSLA .NET helps address a gaping hole. ORM tools (and similar tools) help create entity objects. Workflow is eroding the need for pure process objects. But there remains this need for rich objects that support a RAD development experience for interactive apps. And CSLA .NET helps fill this gap by making it easier for a developer to create objects that implement rich business behaviors and also directly support Windows Forms, Web Forms and WPF interfaces – leveraging the existing RAD capabilities provided by .NET and Visual Studio.

 

Whether a developer (mis)uses CSLA .NET to create data-centric objects, or follows my advice and creates responsibility-driven objects is really their choice. But either way, I think good support for the RAD capabilities of the environment is key to attaining high levels of productivity when building interactive applications.

Wednesday, 03 January 2007 10:40:32 (Central Standard Time, UTC-06:00)  #    Disclaimer

In November Dunn Training held the first ever official CSLA .NET three day class. It was a smashing success, and resulted in a lot of great feedback and comments. Here are a couple quotes from attendees of the November class:

"At first, I was not sold on the need for CSLA.  After attending this class and seeing the examples and proof, I'm on the bandwagon.  This class proved the usefulness of CSLA and sold me on giving up writing all the plumbing myself."

"Miguel and Mark have provided one of the best ways to get up to speed using CSLA."

"The best career enhancing training investment I have made in the last 10 years.  Rocky is lucky to have the DUNN team doing this training.  Great stuff - solid, professional and accurate."

The next class is coming up soon: January 29-31, in Atlanta, GA. If you are looking for three days of intense and practical CSLA .NET training this is your chance!

Wednesday, 03 January 2007 09:41:47 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Tuesday, 02 January 2007

I you had a good holiday season and enjoyed the end of 2006!

 

For my part, I want to thank everyone who contributed to the CSLA .NET forums, and to the CSLAcontrib project. The time and energy you have all put in over the past few months has been a great help to the CSLA .NET community, and I know there are many people out there who are grateful for your efforts!

 

Most importantly though, I want to thank all the users of CSLA .NET and everyone who has purchased copies of my books. At the end of the year I received numerous emails thanking me for creating the framework (and I appreciate that), but I seriously want to thank all of you for making this a vibrant community. CSLA .NET is one of the most widely used development frameworks for .NET, and that is because each of you have taken the time to learn and use the framework. Thank you!

 

For me 2006 was a year of change. Starting with CSLA .NET 2.0 I've been viewing CSLA .NET as not just an offshoot of my books, but as a framework in its own right. Of course many people have been treating it that way for years now, but I hope it has been helpful to have me treat point releases a bit more formally over the past number of months.

 

This extends to version 2.1, which represents an even larger change for me. With version 2.1 I'm releasing my first self-published ebook to cover the changes. This ebook is not a standalone book, rather it is best thought of as a "sequel" to the 2005 book. However, it is well over 150 pages and covers both the changes to the framework itself, as well as how to use the changes in your application development. The ebook is undergoing technical review. That and the editing process should take 2-3 weeks, so the ebook will be available later this month.

 

Looking at the rest of 2007 it is clear that I'll be spending a lot of time around .NET 3.0 and 3.5.

 

I'll be merging the WcfChannel into CSLA .NET itself, as well as implementing support for the DataContract/DataMember concepts. This, possibly coupled with one WPF interface implementation for collections, will comprise CSLA .NET 3.0.

 

It is not yet clear to me what changes will occur due to .NET 3.5, but I expect them to be more extensive. Some of the new C#/VB language features, such as extension methods and lambda expressions, have the potential to radically change the way we think about interacting with objects and fields. When you can add arbitrary methods to any type (even sealed types like String) many interesting options become available.

 

Then there's the impact of LINQ itself, and integration with the ADO.NET Entity Framework in one manner or another.

 

ADO EF appears, at least on the surface, to be YAORM (yet another ORM). If that continues to be true, then it is a great way to get table data into data entities, but it doesn't really address mapping the data into objects designed around use cases and responsibility. If you search this forum for discussions on nHibernate you'll quickly see how ADO EF might fit into the CSLA .NET worldview just like nHibernate does today: as a powerful replacement for basic ADO.NET and/or the DAAB.

 

LINQ is potentially more interesting, yet more challenging. It allows you to run select queries across collections. At first glance you might think this eliminates the need for things like SortedBindingList or FilteredBindingList. I’m not sure that’s true though, because the result of any LINQ query is an IEnumerable<T>. This is the most basic type of list in .NET; so basic that the result must often be converted to a more capable list type.

 

Certainly when you start thinking about n-level undo this becomes problematic. BusinessBase (BB) and BusinessListBase (BLB) work together to implement the undo capabilities provided by CSLA .NET. Running a LINQ query across a BLB results in an IEnumerable<T>, where T is your BB-derived child type. At this point you’ve lost all n-level undo support, and data binding (Windows Forms, and any WPF grid) won’t work right either.

 

So at the moment, I’m looking at LINQ being most useful in the Data Access Layer, along with ADO EF, but time will tell.

 

The point of all this rambling is this: I didn’t rush CSLA .NET 1.0 or 2.0. They came out when I felt I had good understanding of the issues I wanted to address in .NET 1.0 and .20 respectively. And when I felt I had meaningful solutions or answers to those issues. I’m treating .NET 3.5 (and presumably CSLA .NET 3.5) the same way. I won’t rush CSLA .NET to meet an arbitrary deadline, and certainly not to match Microsoft’s release of .NET 3.5 itself. There’s no point coming out with version of CSLA .NET that misses the mark, or that provides poor solutions to key issues.

 

So in 2007 I’ll most certainly be releasing the version 2.1 ebook and CSLA .NET 3.0 (probably with another small ebook). Given that Microsoft’s vague plans are to have .NET 3.5 out near the end of 2007, I don’t expect CSLA .NET 3.5 to be done until sometime in 2008; but you can expect to see beta versions and/or my experiments around .NET 3.5 as the year goes on.

 

Of course I’ll be doing other things beyond CSLA .NET in 2007. I’m lined up to speak at the SD West and VS Live San Francisco conferences in March. I’m speaking in Denver and Boulder later in January, and I’ll be doing other speaking around the country and/or world as the year goes on. Click here for the page where I maintain a list of my current speaking engagements.

 

To close, thank you all for your support of the CSLA .NET community, and for your kind words over the past many months. I wish you all the best in 2007.

 

Code well, have fun!

 

Rocky

Tuesday, 02 January 2007 09:52:48 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Friday, 15 December 2006

Each holiday season my employer, Magenic, gives out a cool tech gift. Over the years we've received things like MP3 players, an XBox, Tivo units and an XBox 360. This year the gift is Microsoft's new Zune device.

For all that I'm a techno-geek, I am also quite conservative when it comes to spending money on devices. They become obsolete so fast, and they are so expensive when new that I just have a hard time spending the money. So I've been still using the Creative Nomad Jukebox 3 I got from Magenic some years ago. It is a nice enough device, with a 20 gig hard drive, good sound recording capabilities as well as perfectly acceptable playback. Creative's PC interface sucks, but I got a 3rd party product called Notmad that totally rocks, and all has been well for years.

But Windows Media Player 11, and the very nice Urge music service, don't support anything as old as my Nomad... So I was getting ready to find a new music device in any case when along comes Magenic with the Zune gift. Thank you Greg and Paul! :)

The Zune device is pretty decent. Plays music, pictures and video. Even with the small screen, video is pretty darn good due to the screen's high quality. And personally I like the radio feature, as I listen to MPR a lot, and listening live beats yesterday's news downloaded via podcast...

The drawback to any of these devices, Zune, Ipod or whatever, is that to get the most out of them you need a subscription to the service. I was hooked on Urge before this, so it is fortunate that Zune has the same basic backend and music selection. Better still, Magenic is covering the cost of the first year's subscription, so now I've got all the music I care to have (and more - they do have country music too, and I just can't stomach that stuff... ;) ).

So I have a playlist of several thousand songs - all the five star music in the MetalCore sub-genre - put it on shuffle and I'm as happy as can be.

Friday, 15 December 2006 14:57:49 (Central Standard Time, UTC-06:00)  #    Disclaimer

The long-awaited release of VS 2005 SP1 is finally here.

Perhaps most importantly, SP1 rolls up a number of hotfixes that many people have been using for a long time to improve the stability and performance of Visual Studio 2005. I know this is one service pack I'm installing immediately!!

Friday, 15 December 2006 11:36:51 (Central Standard Time, UTC-06:00)  #    Disclaimer

I was recently interviewed by Craig Shoemaker for polymorphicpodcast.com, and that interview is now online for listening.

Friday, 15 December 2006 09:40:29 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Wednesday, 13 December 2006

I thought it would be a good idea to give a quick update on the progress/status of the CSLA .NET version 2.1 ebook. Version 2.1 includes some substantial new features and changes as compared to version 2.0, and I am working on an ebook (about 150 pages) that I'll be selling through my web site in the near future. This ebook covers those changes to the framework, both from the framework development perspective and from the perspective of someone who just wants to use the new or changed features.

My original intent was for the ebook to be done in November. Obviously that hasn't happened, though I am very near completion of the book at this point - in the middle of December. There are many reasons for the delay, most notably some serious family health issues (which, unfortunately, are ongoing) and unexpected activities at work (I have a real job in addition to writing ebooks :) ). Those pushed things far enough into November that a number of other, planned, things impacted the schedule as well.

I really didn't expect this project to be this big - I was thinking 75 pages, but it is more like 150. And self-publishing turns out to be more work than I'd thought. Fortunately, a colleague at Magenic is helping to do the technical review and my very talented wife is doing all the non-technical editing. Another Magenic colleague is kindly setting up the online store. And I found out from my tax guy that I need to get a sales tax ID from Minnesota because I have to actually collect sales tax on the ebook - much to my surprise.

Regardless, what this means is that I now expect the ebook to be available for purchase within the first two weeks of 2007. I'm wrapping up the VB version this week, doing technical revisions and final editing and creating the C# version (swapping in different code bits) over the next couple weeks. This should mean the project is done by the end of the year so I can put it online very early in 2007.

Wednesday, 13 December 2006 09:35:06 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Thursday, 30 November 2006

I just learned that two active members of the computer industry and regional community died in a plane crash recently. Details at:

http://www.iowadnug.org/DesktopDefault.aspx

I knew both of these men, having spoken at the Heartland Developers Conference over the past couple years.

I sometimes think about this sort of thing. We live in an increasingly virtual world. While I, like most of us, still have friends that live near me, a great many of my closest friends and colleagues are scattered around the globe. I often interact more with people in Los Angeles, Boston, Europe and Argentina than I do with people where I actually live.

From what I know of Eric and Josh, I think both of them were well-grounded in their real, local world, so the people closest to them really are closest to them, and can mourn together and support each other. And that is a nice thing to consider.

But then I wonder, what about people who's closest friends aren't closest to them physically? How do they support each other in times like this?

I guess time will tell. We're in a period of transition, where the physical world seems to be less and less important relative to the virtual world, and only experience will dictate how we deal with issues like this. One thing is certain, it isn't the technology that matters, it is the people.

My deepest sympathies go to Eric and Josh's families and friends. It is hard to lose anyone, but it is especially hard to lose people in the prime of their lives. People with wives, fiances and children.

Thursday, 30 November 2006 01:44:12 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Monday, 20 November 2006
I am the track chair for Vista Live!, one of the sub-conferences of VS Live! San Francisco. This conference will be held March 25-29, 2007.

As track chair, it is my job to recruit speakers and help select sessions around software development and Windows Vista and .NET 3.0.

Windows Vista has some major impacts on software development. Perhaps most notably, having users (and developers) run in a non-Admin account affects how both development tools and end-user applications install and run. And then there are the new shell features, and integrated RSS support. Add to this .NET 3.0, with WCF, WPF, WF and WCS, and there's a lot of ground to cover.

If you would like to speak at VS Live in March, on a Windows Vista related topic, please use this online proposal submission form to submit your idea.

Monday, 20 November 2006 11:04:58 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Thursday, 16 November 2006

 CSLA .NET 2.1.1 is now available for download from the download page. This is a bug fix release, which addresses some issues in version 2.1. See the change log for details.

Thursday, 16 November 2006 16:04:09 (Central Standard Time, UTC-06:00)  #    Disclaimer
On this page....
Search
Archives
Feed your aggregator (RSS 2.0)
October, 2017 (1)
September, 2017 (3)
August, 2017 (1)
July, 2017 (1)
June, 2017 (1)
May, 2017 (1)
April, 2017 (2)
March, 2017 (1)
February, 2017 (2)
January, 2017 (2)
December, 2016 (5)
November, 2016 (2)
August, 2016 (4)
July, 2016 (2)
June, 2016 (4)
May, 2016 (3)
April, 2016 (4)
March, 2016 (1)
February, 2016 (7)
January, 2016 (4)
December, 2015 (4)
November, 2015 (2)
October, 2015 (2)
September, 2015 (3)
August, 2015 (3)
July, 2015 (2)
June, 2015 (2)
May, 2015 (1)
February, 2015 (1)
January, 2015 (1)
October, 2014 (1)
August, 2014 (2)
July, 2014 (3)
June, 2014 (4)
May, 2014 (2)
April, 2014 (6)
March, 2014 (4)
February, 2014 (4)
January, 2014 (2)
December, 2013 (3)
October, 2013 (3)
August, 2013 (5)
July, 2013 (2)
May, 2013 (3)
April, 2013 (2)
March, 2013 (3)
February, 2013 (7)
January, 2013 (4)
December, 2012 (3)
November, 2012 (3)
October, 2012 (7)
September, 2012 (1)
August, 2012 (4)
July, 2012 (3)
June, 2012 (5)
May, 2012 (4)
April, 2012 (6)
March, 2012 (10)
February, 2012 (2)
January, 2012 (2)
December, 2011 (4)
November, 2011 (6)
October, 2011 (14)
September, 2011 (5)
August, 2011 (3)
June, 2011 (2)
May, 2011 (1)
April, 2011 (3)
March, 2011 (6)
February, 2011 (3)
January, 2011 (6)
December, 2010 (3)
November, 2010 (8)
October, 2010 (6)
September, 2010 (6)
August, 2010 (7)
July, 2010 (8)
June, 2010 (6)
May, 2010 (8)
April, 2010 (13)
March, 2010 (7)
February, 2010 (5)
January, 2010 (9)
December, 2009 (6)
November, 2009 (8)
October, 2009 (11)
September, 2009 (5)
August, 2009 (5)
July, 2009 (10)
June, 2009 (5)
May, 2009 (7)
April, 2009 (7)
March, 2009 (11)
February, 2009 (6)
January, 2009 (9)
December, 2008 (5)
November, 2008 (4)
October, 2008 (7)
September, 2008 (8)
August, 2008 (11)
July, 2008 (11)
June, 2008 (10)
May, 2008 (6)
April, 2008 (8)
March, 2008 (9)
February, 2008 (6)
January, 2008 (6)
December, 2007 (6)
November, 2007 (9)
October, 2007 (7)
September, 2007 (5)
August, 2007 (8)
July, 2007 (6)
June, 2007 (8)
May, 2007 (7)
April, 2007 (9)
March, 2007 (8)
February, 2007 (5)
January, 2007 (9)
December, 2006 (4)
November, 2006 (3)
October, 2006 (4)
September, 2006 (9)
August, 2006 (4)
July, 2006 (9)
June, 2006 (4)
May, 2006 (10)
April, 2006 (4)
March, 2006 (11)
February, 2006 (3)
January, 2006 (13)
December, 2005 (6)
November, 2005 (7)
October, 2005 (4)
September, 2005 (9)
August, 2005 (6)
July, 2005 (7)
June, 2005 (5)
May, 2005 (4)
April, 2005 (7)
March, 2005 (16)
February, 2005 (17)
January, 2005 (17)
December, 2004 (13)
November, 2004 (7)
October, 2004 (14)
September, 2004 (11)
August, 2004 (7)
July, 2004 (3)
June, 2004 (6)
May, 2004 (3)
April, 2004 (2)
March, 2004 (1)
February, 2004 (5)
Categories
About

Powered by: newtelligence dasBlog 2.0.7226.0

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2017, Marimer LLC

Send mail to the author(s) E-mail



Sign In