Just sharing some of my inconsequential lunch conversations with you... RSS  

Tuesday, September 30, 2008

WCF refusing connections after 10 requests

Today I learned the hard way the problem of assuming behavior. I assumed IDisposable would clean up the session, but I was wrong.

It seems like we still have to invoke Close explicitly. The documentation clearly recommends the following pattern:

try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}



I wasn't closing the client proxy, so I was reaching the default WCF 10 concurrent calls limit. The funny thing is that the integration tests were working fine, but not the corresponding ASP.NET usage. Why? Here's a possible explanation:




Hopefully, you were clued in enough to know you need to dispose these objects... but the problem is that (...) the (...) code blocks will cause major problems in a production environment. The choice the WCF developers made here is questionable at best and goes against everything you thought you knew about the IDisposable interface. Everywhere else in the .NET framework, you can count on Dispose cleaning up your object... not so in this case. The problem is that Dispose actually calls Close, and if you are using something like the WsHttpBinding, Close doesn't just clean up resources managed by the object. Close actually needs to make a call to the server and tell the server to clean up your session before it shuts down. When that call back to the server can't be made for any reason--which can happen quite often--Close fires an exception and the object is not disposed. There is another method, Abort, which you need to call to clean up the object's state.

Announcing Visual Studio Team System 2010

Microsoft has published some information about Visual Studio 2010 and the .NET Framework 4.0 today. Here are some links about it:

http://www.microsoft.com/presspass/press/2008/sep08/09-29VS10PR.mspx

http://msdn.microsoft.com/en-us/vstudio/products/cc948977.aspx

Visual Studio Team System 2010 Week on Channel 9:
http://channel9.msdn.com/posts/VisualStudio/Visual-Studio-Team-System-2010-Week-on-Channel-9/

 

Heard about it here.

Sunday, September 28, 2008

jQuery and Microsoft

Uau!... Scott Guthrie as just announced that Microsoft is distributing jQuery with Visual Studio!

This is awesome, instead of re-creating what already exists, Microsoft is learning to integrate. Wouldn't it be incredible if Microsoft didn't have to re-create a DI, a logging platform, a full blown ORM mapper, among others?

Keep them coming. You're on the right track :)

What's wrong with Android?

Ok, Android is a cool phone, but it still lacks a bunch of obvious features like:

  • using it as a modem connected to your laptop;
  • no sync with your computer, pushing Google's mobile web-based applications;
  • no Exchange support;

My old WM6 does it all.

Finally I've got myself a MVC project!

Yes, is true, I finally got myself a real project willing to accept the ASP.NET MVC Preview 5. I'll save my impressions for a future post, for now I'm just interested on sharing my options.

My first thing I had to opt was how to express the model. I've opted by a strongly-typed approach. For the backoffice models I've decided to create the following classes:

    /// <summary>
/// Base class for data driven models.
/// </summary>
public abstract class BaseViewData
{
private readonly List<string> displayList = new List<string>();

/// <summary>
/// List of messages to display.
/// </summary>
public IList<string> DisplayList
{
get
{
return displayList;
}
}
}



This is the base class for all the models - for now it just hold the list of messages to display. Please note that this is the MVC model, not the domain model.



Let's move to the first implementation: ListViewData<T>. This class is a generic of domain model entity classes, and represents a simple listing view data:



    /// <summary>
/// Model view data for simple listing pages.
/// </summary>
/// <typeparam name="T">Domain model entity class.</typeparam>
public class ListViewData<T> : BaseViewData
{
/// <summary>
/// List of items of type T.
/// </summary>
public IList<T> Items { get; set; }
}



Not precisely rocket science, but if simplicity is important to software process in general, adn according to my readings, it seems to be critical for the success of MVC implementations. Armed with this simple classes, we can now do a simple change to the view code behind:



    public partial class List : ViewPage<Models.ListViewData<DomainModel.MyEntity>>
{
}



So we can now fire away our view and code something like:



    <%= Html.DisplayMessages(ViewData.Model.DisplayList)%>



DisplayMessages is a simple extension that implements... the messaging displaying itself...



Now for the grid. I've opted for the MVCContrib Grid implementation. Ok, not as cool as rendering the markup from scratch, but what can I say, I'm lazy.



    <%
Html.Grid<MyEntity>(
ViewData.Model.Items,
column => {
column.For(p => p.Name, "Name");
column.For(p => p.Description, "Description");
column.For(p => Html.ActionLink("Edit", "Edit", new { id = p.ID }), "Edit").DoNotEncode();
column.For(p => Html.ActionLink<MyEntity>(
c => c.Delete(p.ID),
"Delete",
new { onclick = "javascript:return confirm('Confirm operation?');" })
).DoNotEncode();
}
);
%>



The only radical option I had was not to use ASP.NET server-side controls (like repeaters, textboxes and others). If I understand correctly, though these controls can be use on MVC, they are not MVC-ecosystem friendly, as they are fat, not always XHTML compatible, don't guarantee support for accessibility and still depends on ViewState for some operations.



For editing the entity itself, I wrote an equivalent class, ViewData<T>:



    /// <summary>
/// Model view data for simple editing pages.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ViewData<T> : BaseViewData where T : new()
{
private T item = new T();

/// <summary>
/// An item of T.
/// </summary>
public T Item
{
get
{
return item;
}

set
{
item = value;
}
}
}




Same with the view code behind:



    public partial class Edit : ViewPage<Models.ViewData<DomainModel.MyEntity>>
{
}




And with the view itself:



    <form action="<%= ViewData.Model.Item.ID != 0 ? Url.Action("Update", new {id = ViewData.Model.Item.ID}) : Url.Action("Insert") %>" method="post">
<table>
<tr>
<td>Name:</td>
<td><%= Html.TextBox("Name", ViewData.Model.Item.Name)%></td>
</tr>
<tr>
<td>Description:</td>
<td><%= Html.TextBox("Description", ViewData.Model.Item.Description)%></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="<%= ViewData.Model.Item.ID != 0 ? "Update" :" Insert" %>"/></td>
</tr>
</table>
</form>



Naturally not all models depend entirely on a sole Domain Entity. Some do depend on depending entities, like:



    <%
Html.Grid<YetAnotherEntity>(
ViewData.Model.Item.YetAnotherEntities,
column => {
column.For(p => p.Name, "Name");
}
);
%>



But for the rest of the scenarios, we should define a class for the model. Something like:



    public class MySpecialListViewData : ViewPage<Models.ListViewData<DomainModel.AnotherEntity>>
{
public bool ShowSomething { get; set; }
}

Dependent on NDepend

I spend a considerable part of my time reviewing and refactoring code. Code written by interns I coach, master thesis students I accompany, external projects I'm asked to audit, and last but not least my own code.

For ages, code reviewing and refactoring was considered a luxury most projects could easily live without, but on the last years it finally got mainstream acceptance - yes, today I can even explicitly add refactoring tasks to my projects planning :)

Tools have been accompanying this trend. Tool like Resharper on what Patrick Smacchia refers as the micro level (i.e methods' body structuring). But when projects fail technically, they usually do it on a macro level (i.e class, namespace, assembly structuring), and here is where NDepend comes to the rescue.

NDepend is a tool that analyze .NET code base structure against a set of design rules, suggesting refactoring and allowing version metrics comparisons. Yes, making part of my job. Oopss...

Here are some of the basic metrics anyone would expect to find:

And here are some cooler ones:

  • Afferent coupling (Ca): The number of types outside this assembly that depend on types within this assembly. High afferent coupling indicates that the concerned assemblies have many responsibilities.
  • Efferent coupling (Ce): The number of types inside this assembly that depends on types outside this assembly. High efferent coupling indicates that the concerned assembly is dependant. Notice that types declared in framework assemblies are taken into account.
  • Lack of Cohesion Of Methods (LCOM): The single responsibility principle states that a class should not have more than one reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class. There are several LCOM metrics. The LCOM takes its values in the range [0-1]. The LCOM HS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. A LCOM HS value highest than 1 should be considered alarming. 
  • Relational Cohesion (H): Average number of internal relationships per type. Let R be the number of type relationships that are internal to this assembly (i.e that do not connect to types outside the assembly). Let N be the number of types within the assembly. H = (R + 1)/ N. The extra 1 in the formula prevents H=0 when N=1. The relational cohesion represents the relationship that this assembly has to all its types.
  • Instability (I): The ratio of efferent coupling (Ce) to total coupling. I = Ce / (Ce + Ca). This metric is an indicator of the package's resilience to change. The range for this metric is 0 to 1, with I=0 indicating a completely stable package and I=1 indicating a completely instable package.
  • Abstractness (A): The ratio of the number of internal abstract types (i.e abstract classes and interfaces) to the number of internal types. The range for this metric is 0 to 1, with A=0 indicating a completely concrete assembly and A=1 indicating a completely abstract assembly.
  • Distance from main sequence (D): The perpendicular normalized distance of an assembly from the idealized line A + I = 1 (called main sequence). This metric is an indicator of the assembly's balance between abstractness and stability. An assembly squarely on the main sequence is optimally balanced with respect to its abstractness and stability. Ideal assemblies are either completely abstract and stable (I=0, A=1) or completely concrete and instable (I=1, A=0). The range for this metric is 0 to 1, with D=0 indicating an assembly that is coincident with the main sequence and D=1 indicating an assembly that is as far from the main sequence as possible. The picture in the report reveals if an assembly is in the zone of pain (I and A both close to 0) or in the zone of uselessness (I and A both close to 1).

Most of this metrics come with recommendations. For example:

Methods where NbLinesOfCode is higher than 20 are hard to understand and maintain. Methods where NbILInstructions is higher than 40 are extremely complex and should be split in smaller methods (except if they are automatically generated by a tool).

Or this:

Code where the percentage of comment is lower than 20% should be more commented. However overly commented code (>40%) is not necessarily a blessing as it can be considered as an insult to the intelligence of the reader. Guidelines about code commenting can be found here.

Let's give it a try against a small R&D project written with NetTiers. I'll use VisualDepend, the interactive tool. A command line utility is also available, but I'll save it for a future post on continuous integration.

The rules are expressed using a cool DSL for code metrics: Code Query Language (CQL). You can express queries like:

// <Name>A stateless type might be turned into a static type</Name>
WARN IF Count > 0 IN SELECT TOP 10 TYPES WHERE
SizeOfInst ==0 AND
NbInterfacesImplemented == 0 AND // To be accurate, this constraint doesn't take
// account of types that implement some interfaces.
!IsStatic AND
!IsGeneric AND
!IsInterface
// It indicates stateless types that might eventually be turned into static classes.
// See the definition of the SizeOfInst metric here http://www.ndepend.com/Metrics.aspx#SizeOfInst


Cool, you can use the set of rules that come defined out-of-the-box, and you can always write your own.



Here's another favorite of mine:



// <Name>Fields should be marked as ReadOnly when possible</Name>
WARN IF Count > 0 IN SELECT FIELDS WHERE IsImmutable AND !IsInitOnly

// A field that matches the condition IsImmutable is a field that is assigned only by constructors of its class.
// For an instance field, this means its value will remain constant throught the lifetime of the object.
// For a static field, this means its value will remain constant throught the lifetime of the program.
// In both cases, such field can safely be marked with the C# readonly keyword (ReadOnly in VB.NET).

// The condition IsInitOnly matches fields that are marked with the C# readonly keyword (ReadOnly in VB.NET).



And look, we can see it against the metric view:



metricsView



Oopos, lots of potential refactoring here (the blue components)... This view components are directly proportional to the metric - in this case, number of fields by type. Yes, NetTiers appications tend to do it.



As expected, NDepend help you identifying dependencies. For a start, it does it graphically:



dependencies



But graphical dependencies are hard to scale, so the matrix representation is my favorite one to keep track of dependencies:



dependenciesMatrix



Finally an important artifact to give you an idea of where you stand is this graph that represents abstractness and stability:



zones



I read a lot of code - anything I can get my hands on.  One thing I've been doing lately is running NDepend against all the code I can - I find it most educating.



The tool itself is very drillable and effective. The only problem I had with it was the lack of support on some actions on x64, but since version 2.10 full 64 bit support was added.



Give it a try. A must.

Friday, September 26, 2008

Silverlight 2 RC0

Guthrie has just announced it.

I'm having some troubles with visual studio sudden disappearance (the dreadful .NET Runtime version 2.0.50727.3053 - Fatal Execution Engine Error (742A5E00) (80131506)) after SP1 or Silverlight 2 beta2 installation, so I'll probably skip this one.

Sunday, September 21, 2008

Windows 7 M3 Build 6780 Pictures

Here they are Not much revolution here, it looks like some minor shell changes, some old applications got to be redesigned with the Office ribbon, a lighter media player, among others. And UAC seems to be less poppy. Hopefully it will be less resource hungry.

Is Microsoft finally learning to keep their secrets?...

Google is still kicking (Microsoft) asses

The trend doesn't stop: Google search keeps rising, Microsoft plunging. The latest data reports Microsoft US Search dropping below 1 Billion hits last August.

And with respect to Mobile things are preparing to get worse: in a couple of days T-Mobile will release the first Google based phone. A phone with Google's brand and usability and opened to application development will surely eat much of Microsoft's share.

On the browser market, IE is still loosing space against Firefox (ok, Firefox is not Google, nevertheless Google pays 85% of Firefox's bills). And Chrome will rise, the only doubt is who will give away more market share to Google.

So what should Microsoft do about it?

  • Buying out on the search market doesn't seem to help - the obvious choice failed (besides, they are also on a loosing trend). Unless Microsoft can find  a revolutionary search company, Microsoft as to earn this market.
  • Mobile is not as bad as it seems the minute we put a decent shell above it. It looks like some shell and some core apps might do the trick. Here Microsoft as a strong position on the AD/Exchange integration, but that doesn't say much for the consumer market.
  • The browser market is moving the right way: toward W3C compatibility. Though many advogate IE should adopt an open source rendering and javascript engine, Microsoft needs to keep control on IE if not for others, to support it's intranet strategy.
  • Microsoft need to invest more on less resource-hungry systems.

The time to sell just using Microsoft's brand as come to an end. Worse, Microsoft is experiencing a brand erosion effect, at least when compared to Apple and Google's branding.

So part of the solution is on the march: the PC Is not a Stereotype campaign. Ok, it doesn't work against Google, just Apple, but still a great start.

Wednesday, September 17, 2008

Java versus .NET

When talking about Java and .NET people tend to get radical and irrational - I know I do. So I'll try to be write this post as objectively as the sacred .NET and heretic Java deserve.

On the beginning there was C and C++. Well, not exactly the beginning, let's say at the beginning of this war.

Then some enterprises embraced VB as a RAD platform, and VB ruled. VBScript and ASP came following and also ruled.

Then the Devil created Java. Java was beautiful on the blueprints, but lacked maturity. The ubiquity it observed made some believe it would be the solution for enterprise integration - they were wrong, the dictatorship of one language just failed. But slowly Java appeared as a solid enterprise environment, so it started to gain position on the financial markets.

Then God create .NET. It was basically a Java ripp-off, a virtualized environment with a great and well organized class library armed with a solid garbage collector. Where Java environment was multi-platform, .NET was multi-language - yes, today JVM supports a lot of languages, but not back there.

.NET was everything Java wanted to be. Solid, well designed, learning from the Java errors, it only had a problem: it was locked to Windows.

So .NET was immediately accepted even by most of those who hated Microsoft. More, Microsoft promoted a different kind of community, much broader and open-sourced, and it worked! .NET was now the new Java! More, it learned to incorporate Java concepts with ease, so kept growing side-by-side with his evil brother.

.NET had another advantage: it was drawn from one division, so it grew solid and consistent.

So where are we now in respect to Java / .NET war? Well, from my experience:

  • generally .NET is still gaining terrain over Java;
  • Java keeps gaining terrain over .NET on SOA;
  • Java's stronghold is still the financial market;
  • some alpha-geeks lost interest of .NET;
  • Windows Forms desktop application continue to loose interest;
  • Other cool languages and environments still didn't hit the enterprise

Here are some cool links about it:

Monday, September 15, 2008

Mozy doesn't work on my Windows Server 2008

Arghh, I have some hundreds of megs of file standing on Mozy and can't get them into my Windows Server 2008:

MozyHome may not be used for server backups.

What you can do:

Transfer your MozyHome license onto a valid desktop or laptop, or sign up for a MozyPro Server license to back up your server.


Arghh, how can you explain Mozy I use Windows Server 2008 as a desktop?... Well, seem like I have to use Mac to restore them.

Could someone please extend mail?

I waste a lot of time archiving mail by project. So the question is: why can't we just extend mail fields?

Just imagine:

  • Fields would be urn based, and a set of basic fields would define:
  • Mail applications could create templates extending fields;
  • Fields would be sent on reply;
  • When filling fields, mail applications could select from a used list of values.

If we could extend mail, a "Project" field would probably the first one we's use. a

PS: here's how I use the "Project" field today: I embed it on the subject field, something like "[Project A] Kick-off meeting".

Friday, September 12, 2008

I just love guidance

Ok, automated guidance in context is cool, but you can't just replace good old classic guidelines. Here they are, from the patterns & practices App Arch Guide 2.0 Project:

  • Architecture and Design Guidelines
  • Presentation Layer Guidelines
  • Business Layer Guidelines
  • Services Layer Guidelines
  • (from the Guidelines Index page).

    Here's the announcement from J.D. Meier.

    Project location is not trusted on a local drive

    I've been getting some "Project location is not trusted" on my local drive. I've finally decided to google it, and found out the answer here. And yes, it makes sense, the problem arises when downloading code from zip files, leaving the files blocked on a low thrust zone.

    Unblocking all the files is a tedious task, so ZoneStripper is a life safer!

    Dropbox

    I'm trying a free account of Dropbox, a easy to use sync and share tool. For now I'm syncing a Windows and Mac, but I'll probably install it on my Linux desktops. My favorite features: desktop integration (though pretty much Tortoise-like icons...) and version control.

    Here's a cool list of sync utilities: Five Best File Syncing Tools.

    Thursday, September 11, 2008

    Chrome cool links

    I was reading Hanselman's Microsoft IE8 and Google Chrome - Processes are the New Threads and found this cool Chrome links:

    about:network

    about:stats

    about:dns

    about:memory

    <update>

    about:cache

    about:histograms

    </update>

    Wednesday, September 10, 2008

    Scrolling through tabs shortcuts

    Scrolling through tabs is a common operation that can be achieved through CTRL-PageUp and CTRL-PageDown shortcuts. It works on Excel, Firefox, Chrome, but strangely isn't supported on IE8 beta2. Did it stop working, or IE never implemented this useful feature?

    Persistence Ignorance (POCO) Adapter for Entity Framework

    Let's face it: Entity Framework suffers from a huge architectural problem: the business entities are tightly couple with Entity Framework.

    Here a band-aid: Persistence Ignorance (POCO) Adapter for Entity Framework.

    It uses an adapter layer that will translate between POCO objects and Entity Framework-aware objects and provide services on top of POCO objects, such as:

    • Change tracking (snapshot-based and proxy-based when possible)

    • Transparent lazy loading

    • Immutable Value Objects

    • Queries (LINQ and Entity SQL)

    • Shadow state (maintaining certain persistence-related fields outside of entity class)

    It includes a library helper and a code generator which generates the adapter layer.

    And here's Kowalsky's article about it.

    Tuesday, September 09, 2008

    Google just launched a High-resolution satellite

    Google has just launched a High-resolution satellite. The corporation that Claims Ownership of Everything You Create on Chrome, From Blog Posts to Emails, the same that holds much of our mails, consumer habits and search trends, the company that wants a sub-continent-wide radio-frequency, the company that want's to control the internet end-to-end with Chrome (and a sure to come supporting Google OS), that very same corporation now can take high-res pictures for their own usage.

    For some strange reason, people just feel comfortable with this.

    Arghh, I give up.

    Monday, September 08, 2008

    Market Share

    After a brief discussion about Firefox / IE market share with my colleagues, I've (arbitrary) decided to trust MarketShare to tell me this kind of info. According to them, IE falled to 72.15%, and Firefox is still gaining track with 19,73%. Last October it was 78.36% / 14.97%.

    Can you suggest a better stats report?

    Sunday, September 07, 2008

    What is Oslo?

    Douglas Purdy is on his way to PDC, where he will begin unveiling project Oslo. So what is Oslo?

    • A tool that helps people define and interact with models in a rich and visual manner
    • A language that helps people create and use textual domain-specific languages and data models
    • A relational repository that makes models available to both tools and platform components

    So what else is new, Oslo is the modeling platform that will allow us expressing DSLs. But wait, here's what I like about Douglas's vision:

    Oslo is the first step in my vision “to make everyone a programmer (even if they don’t know it)”.

    And this can very well be the first step toward The future of my profession.

    The New Windows Consumer Campaign

    Here is the first Seinfeld / Gates ad. Good news is that is not being offensive to Apple, the bad news is that you must have a master in advertisement to understand it.

    Friday, September 05, 2008

    Google Chrome task manager

    Google Chrome task management is one of the cooler features. And the task manager is just awesome. The only problem I have is that, until the rich RIA applications start poring down on our browsers, the resource we all know that wastes CPU and networking is Flash. And it looks like their is only one and only reference to the Flash plug-in on Chrome task manager:

    image

    That being said, I'd risk to predict that for this class of resource usage, Chrome won't help us identifying the guilty tab for most of our present cases.

    Still a great feature and browser.

    Team Development with Visual Studio Team Foundation Server

    Here's a great TFS guide. Thanks for the tip, Cab_Ux.

    Wednesday, September 03, 2008

    Chrome Privacy?

    Oops, I'm not the only lunatic. Here's another one.

    PS: my hand is raised :)

    <update>

    Here's another one: Google on Chrome EULA controversy

    </update>

    AdBlock for IE8

    Here's a cool IE8 add-on: AdBlock Pro. I've been using it for a week, and it works fine.

    Ad blocking your browser is one of the feature most geeks can't live without. I have mixed emotions about them. Business that depend upon them advertising just hates them. Google will be happy to control ad blocking over their new browser, but until them, you'll have to stick to Firefox and IE to get it done.

    Thanks for the tip, Pita.

    Google Chrome

    Nothing much to say here. Google now has it's browser, Google Chrome. It is opensourced, light and minimalist, fast and easy to use. WebKit is a fast rendering engine, V8 promises to be a faster javascript engine. RIA experience will most probably explode, and this is the best news. Tab fault isolation is my preferred feature. Next is the well designed tab memory management,

    Not all Chrome's features are new - Firefox and IE8 share some if not most of them.

    For now it is quite harmless, but when armed with a future Google minimalist OS, and over Google minimalist window manager, will bring end to end autonomy to Google. Can't it be possible that nobody cares about being totally controlled by Google?

    Now I'm beginning to understand those conspiracy theory lunatics warning us about aliens and underground politics ...

    <update>

    My current experience: IE8 is now the browser that uses less memory. Followed by Chrome (it problably didn't have a chance to make use of it tab memory management features). Firefox3 is absolutely disastrous - please note, I'm loading 7 or 8 add-ins. Some thing with startup time.

    </update>

    Clone Detective for Visual Studio

    Here's an integrated code duplication analyzer: Clone Detective. A Simian like Visual Studio integrated tool. Cool!

    Monday, September 01, 2008

    StyleCop

    I've already blogged about it, but now it seems more mature - and named differently? Anyway, here's a tool to follow. It can help us produce elegant and consistent code. As Fowler wrote:

    Any fool can write code that a computer can understand. Good programmers write code that humans can understand

    Protecting Your Cookies: HttpOnly

    Atwood warned us of an old way to defeat a class of cross-site-scripting. Yes, it deserves a re-issuing and refreshing, but above all we do it the guidance way. Yes, it is there...

    Accessing HyperV over wireless adapter

    It is not new, and quite obvious, the way to access HyperV networking over the wireless adapter. Here's why we can't do it directly:

    The reason for this is because in order to perform our virtual networking - we implement an OSI layer 2 filter driver that creates network packets with the MAC address of the appropriate virtual machine. Unfortunately the wireless networking standard explicitly forbids the creation of network packets with different MAC addresses to that of the physical computer (for security reasons). To handle this - when we detect that we are using a wireless network adapter we create packets where some of the MAC addresses in the packet match that of the virtual machine - while the other MAC addresses match that of the physical computer.
    It seem like it was too much AP dependent - sometimes it worked, sometime it didn't.

    Development Catharsis :: Copyright 2006 Mário Romano