答:
I feel that often this practice can be used badly.

For example, say you are using the MongoDB client to access your Mongo database. Wrapping the client itself while still exposing all its functionality is pretty hard. You'll have to implement a query object and transform it to the propitiatory one etc. Its a lot of work and if you do change the client later you may find that the new one follows a completely different pattern and your interfaces and wrapper classes are no longer appropriate.

However, you do want to be able to inject mocked objects etc for testing and generally avoid making other stuff dependent on the thrid party library.

This can still be achieved if you wrap at a higher level, say following the repository pattern. By wrapping at this higher level you avoid having to deal with all the details of the 3rd party library and can expose a limited and constant interface which is relevant to your code, rather than the external code you are wrapping.


问:
Handle files on a remote location
Our intranet application is used to document and store office files. Both app and server are hosted remotely on the same server. Due to fact that our app server is changed every couple of years, we want to store files on a machine/location other then the app server.

Since app and files were at the same location it was easy to manipulate files, but with this change I am interested what should we be aware of?

We need to be able to upload, edit, rename, delete files. Are cloud service only way to make this happen?

答:
A simple approach could be:

Set up a file server. For good performance it should have good connectivity to the app server, preferably in the same network.

If you choose the SMB protocol, this could be a windows file server or a linux server using samba.

Mount the share on the app server as a drive letter.

This can be done using net use Q: \\FileServer\ShareName on the command line. Windows explorer includes some GUI for this as well, but I forgot the details.

Then use the files as if they were local. The latency and bandwidth limitations of the connection might lead to reduced performance, especially if the server is far away.

I think SMB is the only protocol where mounting is built into windows, but you could use other protocols by installing appropriate third party software.

A different approach modifying your application to use some storage API. For example the Amazon S3 API is relatively popular. Note that this does not require you to use Amazon S3, since there are other implementations of this API.

ContentLicense: CC BY-SA 3.0

Title: Handle files on a remote location


问:
Why are the sizes of programs so large?
If we look at the vintage program Netscape Navigator or an early version of Microsoft Word, those programs were less than 50 MB in size. Now when I install google chrome it is 200 MB and desktop version of Slack is 300 MB. I read about some rule that programs will take all available memory no matter how much it is but why?

Why are the current sizes of programs so large compared to 10 or 15 years ago? The programs are not doing significantly more functions and do not look very different. What is it that is the resource hog now?

答:
While the graphics/usability are indeed contributing factors, there's an awful lot of it that's library/excess compiled code.

Example of how small code CAN still be:  MenuetOS, a full 64-bit OS with powerful apps that fits on a single floppy disk.

Example of how big code can be for no obvious reason:  I did a simple text output "Hello, World!" in Ada recently.  The compiled executable was over 1 MiB!.  Same executable in assembly is just a KiB or 2 (and the bulk of that is executable overhead, the actual running code is tens of bytes).

Title: Why are the sizes of programs so large?


问:
How do web developers deal with editing (pre-processed) vendor prefixed CSS in browser dev tools?
I have a dillema working with CSS. I use a pre-processor to add all necessary vendor prefixes to CSS when it's served, keeping my source code short and simple. However the issue is, by far the most effective way to to edit styles realistically (and see real-time updating of the page) is to use the web page's dev tools in whichever browser(s) you're currently testing, edit the CSS there, and copy/paste it to the source code after making significant changes.

So then my CSS source code is full of vendor prefixes.

Is there a simple solution to this? What solutions exist to solve this problem?

答: Sounds like you need a de-processor to remove the prefixes. Could you write one in JavaScript and embed it in a local page? What I'm imagining is a page with two text boxes, you copy your modified CSS into one box, press a button to run the prefix-removal code, and the un-prefixed code appears in the other text box. Then you simply C&P the processed code back into your application source. If you're really good you could probably write a browser extension to de-prefix whatever code is highlighted and display it in a separate dialog, but I'm nowhere near that good so I really can't guess how much effort that would take.</p>


问:
Wrapping third party library is best practice
I came across with following statements while reading the Clean Code book of Robert C. Martin.

Chapter : 7 :  Error Handling
 Page No : 109

  ..In fact, wrapping third-party APIs is a best practice. When you wrap
  a third-party API, you minimize your dependencies upon it: You can
  choose to move to a different library in the future without much
  penalty. Wrapping also makes it easier to mock out third-party calls
  when you are testing your own code.

 One ﬁnal advantage of wrapping is
  that you aren’t tied to a particular vendor’s API design choices. You
  can deﬁne an API that you feel comfortable with.

I am quite confused about the bold part.

I am totally clueless how can we move to different library so easily if we wrap the third party library and how testing becomes easy with it ?

答:
There are differing opinions voiced, but I doubt people fundamentally disagree.

The point is that wrapping APIs can be best practice.

If the interface of the API is trivial, then there's no point in wrapping. Same if the interface is stable, doesn't get in the way of testing, and isn't much more complicated than what you need.

If the interface is complicated and you only use a subset, use a wrapper. For example, an advanced logging framework where you always want to log things in the same format and all you ever use in the app is LogError, LogWarn, LogInfo, and LogDebug. Using a wrapper allows using a mock for testing log messages, and also allows to easily change the implementation

If the interface is complicated because it has to be, and you use all of it, you won't be able to improve the interface and the wrapper will be as complicated as the original interface. That means a wrapper won't offer a benefit when moving to a different library.


问:
Should every member of a team use the same IDE?
Do you think it makes sense to enforce that every member of a team must use the same IDE?

For instance all engineers that are already on the team use IDE X. Two new engineers come and want to use IDE Y instead because that's what they have been using for several years now.

Do you have any experience with "mixed IDE" teams? If so what is it?

答:
Sounds a bit like "we used this at my old job". Well, they aren't at their old job.

If it doesn't affect your tool chain or source control plug.ins, then maybe yes. Then again, can the two new folk demonstrate a clear benefit? Have they used your IDE?

Otherwise, I have no patience with this nonsense unless there is a good case for it. They aren't at their old job: it couldn't have been that good for them to want to leave. Was using the other IDE the only highlight in ther old job: if so, they should STFU and be grateful..

ContentLicense: CC BY-SA 2.5


答:
I read about some rule that programs will take all available memory no
  matter how much it is but why?

That's not quite true. Systems will not release memory they have consumed until the operating system comes under memory pressure. This is a performance improvement. If you were browsing a page with images on, you navigate away. You might navigate back, therefore needing the image again. If the operating system has the RAM there is no point in clearing the memory until you are sure you won't need it again.

Clearing the memory immediately would take CPU cycles and memory bandwidth away from the user when they are probably most likely wanting highly responsive web pages to be displayed on screen.

The operating system will consume all available non application memory, the majority of which is for the file system cache.

Memory management is a hard problem but there are very clever people working on it all the time. Nothing is being wasted on purpose and the key goal is to provide you with a very responsive computer.

Title: Why are the sizes of programs so large?

Body:
If we look at the vintage program Netscape Navigator or an early version of Microsoft Word, those programs were less than 50 MB in size. Now when I install google chrome it is 200 MB and desktop version of Slack is 300 MB. I read about some rule that programs will take all available memory no matter how much it is but why?

Why are the current sizes of programs so large compared to 10 or 15 years ago? The programs are not doing significantly more functions and do not look very different. What is it that is the resource hog now?


答:
Disclaimer: I wrap the middleware of my own company...

There are multiple claims here, so I will address them separately.

Wrapping also makes it easier to mock out third-party calls when you are testing your own code.

There are several benefits here, specifically when mocking just counting the number of calls helps. Some will argue that the number of calls is not functional and therefore should not be tested; however I have seen people introducing changes which multiplied the number of calls by a factor of 10x or 100x, and the performance implications are not trivial. This is especially true when...

... some 3rd party libraries come with a lot of dependencies (network connection, complicated configuration file) and only by mocking can you easily inject errors, among other specific situations you wish to test for.

Of course, at this point, wrapping is more down to get rid of an unwanted dependency (connection, configuration file) than anything else.

..In fact, wrapping third-party APIs is a best practice. When you wrap a third-party API, you minimize your dependencies upon it: You can choose to move to a different library in the future without much penalty.

This should go hand in hand with the DRY principle and with abstraction.

When calling a 3rd party library to parse a XML document, then navigate it to extract some pieces of data, the caller:

is not interested in which 3rd party library you use

is probably not interested in the structure of the XML document

as a result, you will wrap this into some code of your own, which has the double benefits of elevating the abstraction level (it's not a XML document, it's a request to buy 4 vanilla ice creams, with caramel on top).

If you repeatedly decode XML documents, quite rapidly you will naturally fuse parts of the decoding code which comes up over and over. This is just DRY.

As a result, I find than wrapping 3rd party components come naturally: whenever I use the same call twice or thrice, I tend to extract the code in a common function, which somehow becomes a wrapper.

(unasked question about boundaries and business model)

A 3rd party API is a foreigner, it does not speak your language.

There is a boundary between your own code and the 3rd party code: you use different objects. For example, you may model your server as a string (IPv4) and integer (port) but the underlying API expects just a string (IPv4:port), or vice versa. As a result, a transformation needs to be applied when talking to this foreign API.

Ideally, you want to maximize the amount of code dealing with your own data:

you understand it

you control it (invariants are checked and meaningful for your app.)

...

this requires pushing the boundaries of foreign code as far as possible.

Also, because each translation carries its own mismatch impedance risk, you want to reduce the number of places in the code where such translation occur.

In both cases, this argues for a thin layer between your application code and 3rd party APIs.

Title: Wrapping third party library is best practice

Body:
I came across with following statements while reading the Clean Code book of Robert C. Martin.

Chapter : 7 :  Error Handling
 Page No : 109

  ..In fact, wrapping third-party APIs is a best practice. When you wrap
  a third-party API, you minimize your dependencies upon it: You can
  choose to move to a different library in the future without much
  penalty. Wrapping also makes it easier to mock out third-party calls
  when you are testing your own code.

 One ﬁnal advantage of wrapping is
  that you aren’t tied to a particular vendor’s API design choices. You
  can deﬁne an API that you feel comfortable with.

I am quite confused about the bold part.

I am totally clueless how can we move to different library so easily if we wrap the third party library and how testing becomes easy with it ?


问:
Creating variations of a property heavy class
What kind of pattern or design can prevent the creation of a class packed with properties that aren't always used?

Example

```<code>class Car{
   public string type;
   public string name;
   public DateTime manufactured;
   public int model;
   public Color color;
   public int VIN;
   // ..and on
}

public Car(string name, Color color){
    this.name = name;
    this.color = color;
}
</code>```

Sometimes you want to make a Car with just some info, like the make and model, but you always want it to have a few defaults. How do you avoid 20 children classes or constructor overloads in this case?

答:
The way to avoid having to have a zillion overloads in the constructor is to assign to your properties (they should be properties, BTW, not fields,) outside of the constructor.

Sometimes you want to make a Car with just some info, like the make and model, but you always want it to have a few defaults.

Then do exactly that: have the constructor require the required info, and then set the rest of the properties to defaults.  Then you can call the constructor with extra-property syntax if you want to override those defaults:

```<code>var myCar = new Car("Ford", "Taurus") {Color = ModelColors.Blue, VIN = myVIN};
</code>```

Body:
The way to avoid having to have a zillion overloads in the constructor is to assign to your properties (they should be properties, BTW, not fields,) outside of the constructor.

Sometimes you want to make a Car with just some info, like the make and model, but you always want it to have a few defaults.

Then do exactly that: have the constructor require the required info, and then set the rest of the properties to defaults.  Then you can call the constructor with extra-property syntax if you want to override those defaults:

var myCar = new Car("Ford", "Taurus") {Color = ModelColors.Blue, VIN = myVIN};


问:
How to design access to different type objects in protocol response
I have written a communication library for an industrial device protocol. The response frame contains a byte array as payload data.
The payload data consists of several "objects“ of different types, like integers, floats and  other, more complex data like dates or different string encodings. To make this more fun, the data could also be in different byte order.

My current solution is to have a generic data object, which holds the general information like position in the byte array and byte order, and several inherited objects to handle the different data-types:

```<code>public abstract class DataObject{
    private readonly int _position;
    public int Position {
        get { return _position; }
    }
    private readonly ByteOrder _byteOrder;
    public abstract object Data { get;}

    /* snip */
}

public class FloatObject : DataObject {
    public abstract object Data {
        get{
            float floatValue;
            /* handle byte to float conversion */
            return floatValue;
        }
    }
}

public class StringObject : DataObject {
    public abstract object Data {
        get{
            string stringValue;
            /* handle byte to string conversion */
            return stringValue;
        }
    }
}
</code>```

What I do not like about this is the handling of the Data-property. The base class declares it as an object, so every time I need to cast the result to the corresponding type. If I do not declare a Data-property in the base class, but in all the derived classes, I need to cast the data-object to the specific data-object, which is just a shift of the problem.
Is there any better design I could use to solve this problem?

答:
I doubt anything can be done around your current design to avoid casting.

When developing from scratch, I would recommend to avoid creation of too abstractly typed fields in classes, responsible for protocol handling. Remember LSP!

Instead of inventing your own protocol format and serializers/deserializer, it would be interesting to look at Google Protocol Buffers or gRPC.


答:
If you declare a type that's actually supposed to contain useful state as object, there is really no way to avoid typecasts all over.  There's no way around it.

However, it seems that what you're doing, at a higher level, is attempting to extract information from a stream of bytes by applying formal rules to recognize well-defined patterns in the input, and produce data objects from them representing their semantic meaning.

This is a well-studied problem in computer science: parsing.  The term is generally used in the context of text, source code for a programming language, but there's no reason you couldn't apply the same techniques to a binary stream.  If I had to work with a system as complicated as you're describing, one of the first things I'd do is write a parser for it.

Exactly how to go about doing that depends heavily on how the data stream is defined, but you can probably use existing tools such as Protocol Buffers, or a parser-generator like ANTLR to take care of a lot of the heavy lifting.

Title: How to design access to different type objects in protocol response

Body:
I have written a communication library for an industrial device protocol. The response frame contains a byte array as payload data.
The payload data consists of several "objects“ of different types, like integers, floats and  other, more complex data like dates or different string encodings. To make this more fun, the data could also be in different byte order.

My current solution is to have a generic data object, which holds the general information like position in the byte array and byte order, and several inherited objects to handle the different data-types:

```<code>public abstract class DataObject{
    private readonly int _position;
    public int Position {
        get { return _position; }
    }
    private readonly ByteOrder _byteOrder;
    public abstract object Data { get;}

    /* snip */
}

public class FloatObject : DataObject {
    public abstract object Data {
        get{
            float floatValue;
            /* handle byte to float conversion */
            return floatValue;
        }
    }
}

public class StringObject : DataObject {
    public abstract object Data {
        get{
            string stringValue;
            /* handle byte to string conversion */
            return stringValue;
        }
    }
}
</code>```

What I do not like about this is the handling of the Data-property. The base class declares it as an object, so every time I need to cast the result to the corresponding type. If I do not declare a Data-property in the base class, but in all the derived classes, I need to cast the data-object to the specific data-object, which is just a shift of the problem.
Is there any better design I could use to solve this problem?


答:
Have you examined this possibility?

```<code>public abstract class DataObject<T>
    public byte[] RawData { get;}
    public abstract object DataAsObject { get;}
    public abstract T Data { get;}
public class FloatObject : DataObject<float>
    public float Data { get { ... } }
public class StringObject : DataObject<string>
    public string Data { get { ... } }
</code>```

Is there any reason why it would not work, that I cannot see right now?

Body:
Have you examined this possibility?

public abstract class DataObject<T>
    public byte[] RawData { get;}
    public abstract object DataAsObject { get;}
    public abstract T Data { get;}
public class FloatObject : DataObject<float>
    public float Data { get { ... } }
public class StringObject : DataObject<string>
    public string Data { get { ... } }

Is there any reason why it would not work, that I cannot see right now?


问:
Using third-party libraries - always use a wrapper?
Most projects I am involved with use several open-source components. As a general principle, is it a good idea always to avoid binding all components of the code to the third-party libraries and instead go via an encapsulating wrapper to avoid the pain of change?

As an example, most of our PHP projects directly use log4php as a logging framework, i.e. they instantiate via \Logger::getLogger(), they use ->info() or ->warn() methods, etc. In the future, however, a hypothetical logging framework may appear which is better in some way. As it stands, all the projects which closely couple to the log4php method signatures would have to change, in dozens of places, in order to fit the new signatures. This would obviously have a wide impact on the codebase and any change is a potential problem.

To future-proof new codebases from this kind of scenario, I often consider (and sometimes implement) a wrapper class to encapsulate the logging functionality and make it easier, though not foolproof, to alter the way in which logging works in future with minimal change; the code calls the wrapper, the wrapper passes the call to the logging framework du jour.

Bearing in mind that there are more complicated examples with other libraries, am I over-engineering or is this a wise precaution in most cases?

EDIT: More considerations - using dependency injection and test doubles practically requires that we abstract out most APIs anyway ("I want to check my code executes and updates its state, but not write a log comment/access a real database"). Isn't this a decider?

答:
By wrapping a third party library you add an additional layer of abstraction on top of it. This has a few advantages:

Your code base becomes more flexible to changes

If you ever need to replace the library with another one you only need to change your implementation in your wrapper - in one place. You can change the implementation of the wrapper and don't have to change a thing about anything else, in other words you have a loosely coupled system. Otherwise you would have to go through your whole codebase and make modifications everywhere - which is obviously not what you want.

You can define the API of the wrapper independently of the API of the library

Different libraries can have vastly different APIs and at the same time none of them may be exactly what you need. What if some library needs a token to be passed along with every call? You can pass the token around in your app wherever you need to use the library or you can safe it somewhere more centrally, but in any case you need the token. Your wrapper class makes this whole thing simple again - because you can just keep the token inside your wrapper class, never exposing it to any component inside your app and completely abstract away the need for it. A huge advantage if you ever used a library which does not emphasise good API design.

Unit testing is way simpler

Unit tests should only test one thing. If you want to unit test a class you have to mock its dependencies. This becomes even more important if that class makes network calls or accesses some other resource outside of your software. By wrapping the third party library it is easy to mock those calls and return test data or whatever that unit test requires. If you don't have such a layer of abstraction it becomes much more difficult to do this - and most of the time this results in a lot of ugly code.

You create a loosely coupled system

Changes to your wrapper have no effect on other parts of your software - at least as long as you don't change the behaviour of your wrapper. By introducing a layer of abstraction like this wrapper you can simplify calls to the library and and almost completely remove the dependency of your app on that library. Your software will just use the wrapper and it won't make a difference how the wrapper is implemented or how it does what it does.

Practical Example

Let's be honest. People can argue about the advantages and disadvantages of something like this for hours - which is why I much rather just show you an example.

Let's say you have some kind of Android app and you need to download images. There are a bunch of libraries out there which make loading and caching images a breeze for example Picasso or the Universal Image Loader.

We can now define an interface which we are going to use to wrap whichever library we end up using:

```<code>public interface ImageService {
    Bitmap load(String url);
}
</code>```

This is the interface we can now use throughout the app whenever we need to load an image. We can create an implementation of this interface and use dependency injection to inject an instance of that implementation everywhere we use the ImageService.

Let's say we initially decide to use Picasso. We can now write an implementation for ImageService which uses Picasso internally:

```<code>public class PicassoImageService implements ImageService {

    private final Context mContext;

    public PicassoImageService(Context context) {
        mContext = context;
    }

    @Override
    public Bitmap load(String url) {
        return Picasso.with(mContext).load(url).get();
    }
}
</code>```

Pretty straight forward if you ask me. Wrapper around libraries don't have to be complicated to be useful. The interface and the implementation have less than 25 combined lines of code so it was barely any effort to create this, but already we gain something by doing this. See the Context field in the implementation? The dependency injection framework of your choice will already take care of injecting that dependency before we ever use our ImageService, your app now does not have to care about how the images are downloaded and whatever dependencies that library may have. All your app sees is an ImageService and when it needs an image it calls load() with with an url - simple & straightforward.

However the real benefit comes when we start to change things. Imagine we now need to replace Picasso with Universal Image Loader because Picasso does not support some feature we absolutely need right now. Do we now have to comb through our codebase and and tediously replace all the calls to Picasso and then deal with dozens of compile errors because we forgot to a few Picasso calls? No. All we need to do is create a new implementation of ImageService and tell our dependency injection framework to use this implementation from now on:

```<code>public class UniversalImageLoaderImageService implements ImageService {

    private final ImageLoader mImageLoader;

    public UniversalImageLoaderImageService(Context context) {

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
                .defaultDisplayImageOptions(defaultOptions)
                .build();

        mImageLoader = ImageLoader.getInstance();
        mImageLoader.init(config);
    }

    @Override
    public Bitmap load(String url) {
        return mImageLoader.loadImageSync(url);
    }
}
</code>```

As you can see the implementation might be very different, but it does not matter. We didn't have to change a single line of code anywhere else in our app. We use a completely different library which might have completely different features or might be used very differently but our app just does not care. Same as before the rest of our app just sees the ImageService interface with its load() method and however this method is implemented does not matter any more.

At least to me this all already sound pretty nice already, but wait! There's still more. Imagine you are writing unit tests for a class you are working on and this class uses the ImageService. Of course you can't let your unit tests make network calls to some resource located on some other server but since you are now using the ImageService you can easily let load() return a static Bitmap used for the unit tests by implementing a mocked ImageService:

```<code>public class MockImageService implements ImageService {

    private final Bitmap mMockBitmap;

    public MockImageService(Bitmap mockBitmap) {
        mMockBitmap = mockBitmap;
    }

    @Override
    public Bitmap load(String url) {
        return mMockBitmap;
    }
}
</code>```

To summarize by wrapping third party libraries your code base becomes more flexible to changes, overall simpler, easier to test and you reduce the coupling of different components in your software - all things that get more and more important the longer you maintain a software.

Body:
By wrapping a third party library you add an additional layer of abstraction on top of it. This has a few advantages:

Your code base becomes more flexible to changes

If you ever need to replace the library with another one you only need to change your implementation in your wrapper - in one place. You can change the implementation of the wrapper and don't have to change a thing about anything else, in other words you have a loosely coupled system. Otherwise you would have to go through your whole codebase and make modifications everywhere - which is obviously not what you want.

You can define the API of the wrapper independently of the API of the library

Different libraries can have vastly different APIs and at the same time none of them may be exactly what you need. What if some library needs a token to be passed along with every call? You can pass the token around in your app wherever you need to use the library or you can safe it somewhere more centrally, but in any case you need the token. Your wrapper class makes this whole thing simple again - because you can just keep the token inside your wrapper class, never exposing it to any component inside your app and completely abstract away the need for it. A huge advantage if you ever used a library which does not emphasise good API design.

Unit testing is way simpler

Unit tests should only test one thing. If you want to unit test a class you have to mock its dependencies. This becomes even more important if that class makes network calls or accesses some other resource outside of your software. By wrapping the third party library it is easy to mock those calls and return test data or whatever that unit test requires. If you don't have such a layer of abstraction it becomes much more difficult to do this - and most of the time this results in a lot of ugly code.

You create a loosely coupled system

Changes to your wrapper have no effect on other parts of your software - at least as long as you don't change the behaviour of your wrapper. By introducing a layer of abstraction like this wrapper you can simplify calls to the library and and almost completely remove the dependency of your app on that library. Your software will just use the wrapper and it won't make a difference how the wrapper is implemented or how it does what it does.

Practical Example

Let's be honest. People can argue about the advantages and disadvantages of something like this for hours - which is why I much rather just show you an example.

Let's say you have some kind of Android app and you need to download images. There are a bunch of libraries out there which make loading and caching images a breeze for example Picasso or the Universal Image Loader.

We can now define an interface which we are going to use to wrap whichever library we end up using:

public interface ImageService {
    Bitmap load(String url);
}

This is the interface we can now use throughout the app whenever we need to load an image. We can create an implementation of this interface and use dependency injection to inject an instance of that implementation everywhere we use the ImageService.

Let's say we initially decide to use Picasso. We can now write an implementation for ImageService which uses Picasso internally:

public class PicassoImageService implements ImageService {

    private final Context mContext;

    public PicassoImageService(Context context) {
        mContext = context;
    }

    @Override
    public Bitmap load(String url) {
        return Picasso.with(mContext).load(url).get();
    }
}

Pretty straight forward if you ask me. Wrapper around libraries don't have to be complicated to be useful. The interface and the implementation have less than 25 combined lines of code so it was barely any effort to create this, but already we gain something by doing this. See the Context field in the implementation? The dependency injection framework of your choice will already take care of injecting that dependency before we ever use our ImageService, your app now does not have to care about how the images are downloaded and whatever dependencies that library may have. All your app sees is an ImageService and when it needs an image it calls load() with with an url - simple & straightforward.

However the real benefit comes when we start to change things. Imagine we now need to replace Picasso with Universal Image Loader because Picasso does not support some feature we absolutely need right now. Do we now have to comb through our codebase and and tediously replace all the calls to Picasso and then deal with dozens of compile errors because we forgot to a few Picasso calls? No. All we need to do is create a new implementation of ImageService and tell our dependency injection framework to use this implementation from now on:

public class UniversalImageLoaderImageService implements ImageService {

    private final ImageLoader mImageLoader;

    public UniversalImageLoaderImageService(Context context) {

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
                .defaultDisplayImageOptions(defaultOptions)
                .build();

        mImageLoader = ImageLoader.getInstance();
        mImageLoader.init(config);
    }

    @Override
    public Bitmap load(String url) {
        return mImageLoader.loadImageSync(url);
    }
}

As you can see the implementation might be very different, but it does not matter. We didn't have to change a single line of code anywhere else in our app. We use a completely different library which might have completely different features or might be used very differently but our app just does not care. Same as before the rest of our app just sees the ImageService interface with its load() method and however this method is implemented does not matter any more.

At least to me this all already sound pretty nice already, but wait! There's still more. Imagine you are writing unit tests for a class you are working on and this class uses the ImageService. Of course you can't let your unit tests make network calls to some resource located on some other server but since you are now using the ImageService you can easily let load() return a static Bitmap used for the unit tests by implementing a mocked ImageService:

public class MockImageService implements ImageService {

    private final Bitmap mMockBitmap;

    public MockImageService(Bitmap mockBitmap) {
        mMockBitmap = mockBitmap;
    }

    @Override
    public Bitmap load(String url) {
        return mMockBitmap;
    }
}

To summarize by wrapping third party libraries your code base becomes more flexible to changes, overall simpler, easier to test and you reduce the coupling of different components in your software - all things that get more and more important the longer you maintain a software.


问:
Using Subversion as an artifact repository vs a specific artifact management tool
TL;DR: Why use something like Apache Archiva or Sonatype Nexus as an artifact repository instead of Subversion?

The build system I use currently has a lot of binary blobs (images, sound files, compiled binaries, etc), both as input and output to our builds. Our system for managing these is very ad hoc; some are checked into our Subversion repository alongside our code, some are stored elsewhere outside any formal version control.

I'm looking at consolidating this, so we have something that's more self-consistent and easy to use, and which separates binary artifacts from code.

Google tells me there are a selection of artifact repositories available (Archiva, Nexus, Artifactory, …), but from reading around, I can't see any advantage to using these over Subversion. That will look after the binaries for us – it already does that for some of our binaries, we'd just want to rearrange the repository layout to separate them from code – and has the notable advantage that we already have Subversion servers and expertise.

So. What's the advantage of using a dedicated artifact management system over using a general version control tool like Subversion?

答:
We use SVN as a repository for release builds and it does very well.  We have in one release repository better than 30gb of various release builds and it performs well pulling builds out for deploy.

some of the advantages of doing this are..

Binaries added to SVN are compressed nearly 60-70 percent on avg saving space.

SVN serves as a library (artifactory) for releases and the repository is backed up for Disaster Recovery purposes.

SVN via https allows for secure delivery of release code into a DMZ.


问:
Are hooks really subsumed by Slim Framework middleware?
I've been using the Slim Framework (v2) for a little while now to develop my user management system.

They recently released Slim 3, and according to the upgrade guide,

Slim v3 no longer has the concept of hooks. Hooks were removed as they duplicate the functionality already present in middlewares. You should be able to easily convert your Hook code into Middleware code.

I'm not quite sure if I believe this.  Slim's middleware allows you to modify the request before it hits your main application, or modify the response before it is sent out to the client.

However, this says nothing of modifying the behavior of the application itself, which hooks can do easily - the application simply anticipates points in the code where someone might want to modify the behavior, and call applyHook accordingly.

From what I can tell, the only way to modify the core behavior of an application via middleware is via exceptions - the middleware throws an exception, which the core application catches, and then does something else.  But this seems to me an abuse of the framework, and I have a hard time believing that this is what they mean.

Do hooks really "duplicate the functionality already present in middlewares"?

答:
From my understanding of hooks this is true. The way I understand hooks it that you can execute some code at a predefined point during the execution flow. Afterwards the application continues as if nothing happened. This is very abstract so I would like to express this using an example:

Lets say you can execute code when an before_authentication hook is encountered. Maybe you would like to initialize sessions before authentication and would therefore do this here. This can also be done through middleware.

Lets say you have a middleware component which handles authentication. Each middleware is defined inside an array and are executed in the defined order. You would then insert your InitializeSessionMiddleware component just before AuthenticationMiddleware is defined in the array.

Both of these solutions would work, but since Slim (AFAIK) is very HTTP focused, it would be more appropriate to write this as middleware.

Please keep in mind this is my understanding of midddleware and hooks. If you would like to modify how the application works at predefined points, I would look into exposing some callbacks, which has a predefined structure (interface?) unique for that specific point. This callback could be changed if the structure is correct.

I hope this can help you, happy coding.


问:
How do you dive into large code bases?
What tools and techniques do you use for exploring and learning an unknown code base?

I am thinking of tools like grep, ctags, unit-tests, functional test, class-diagram generators, call graphs, code metrics like sloccount, and so on. I'd be interested in your experiences, the helpers you used or wrote yourself and the size of the code base with which you worked.

I realize that becoming acquainted with a code base is a process that happens over time, and familiarity can mean anything from "I'm able to summarize the code" to "I can refactor and shrink it to 30% of the size". But how to even begin?

答:
This happens a lot. Until I started to work on an open source platform I don't think I ever started a job which didn't start out with an admission that the code had some 'quirks'.

You can get a long way with a step debugger and a lot of tenacity. Unfortunately often it takes time and experience to learn a particular big ball of mud and even then after years there can still be some subsystem which crops up which nobody has any knowledge of.

Title: How do you dive into large code bases?


问:
Best practise for databinding when a non-data object is included with the data
I'm using .NET with Windows Forms, but I believe there may be similar concerns with other toolkits.

Suppose we have a list of objects of a certain type. Using an example to make the following easier to read, suppose there is a Category class to represent them. We display a list of them to allow a user to filter articles by category. Binding the ListBox component to a data source of Category objects is a way to do so.

What would be the best way to add an entry labelled "All" in the same ListBox? Assume that it has to be in the list, and not as a separate option like a radio button.

I can think of the following approaches, but all of them seem to have a drawback.

Create a "dummy" Category instance named "All" and an invalid ID.

This is the easiest way but it feels wrong conceptually, as "All" is not actually a category (no article belongs to a category named that). Also, depending on the framework the UI may not be allowed to create Category objects.

Don't use data binding at all; populate the list box with strings and use the selection's index to get the object from the data source.

This may beat the point of having data bound controls, and adds potential problems: What if we also want to add a "None" entry in the future? We'll have to increment the list box's selected index by 2 instead of 1 to get the correct object from the data source.

Use an intermediate class, CategoryListItem, to populate the list box with. It has a reference/pointer to a Category which is null for dummy entries.

This one may be more elegant, but it adds the overhead of creating a new list of CategoryListItem instances for every list of Category instances we want to display.

Is one of the above a recommended way to data bind to such a component, or perhaps a way I haven't thought of?

答:
Do not bind your objects directly to the ListBox (I suppose you did that by adding each category object separately, because I don't know any way to set the DataSource property to a list of objects).

My suggestion:

Create an Enum EnumCategory, which contains values of all possible categories, including ‘all‘ and 'none' and whatever you like. Bind this Enum as DataSource to the ListBox (also works for a combobox).

By this you can enhance your Enum whenever you like without problems.

If you also need comfortable names (including spaces and other chars that do not belong into variable names) or multilanguage support, let me know.   Both can be added easily.


答:
What you want is live/hot reload.

If you use live reloading, as soon as you make and save a change to your css file, the tools will rebuild the final css and load the new version into the browser. No need to refresh, it just happens. That way you can make change and see quick feedback, just like if you had modified the dev tools in the browser. But your changes are already in your source (no need to copy back).

How do to this depends on your the rest of your stack. But the chances are that whatever tool you are using to build your css: grunt/gulp/webpack/etc has addons to support livereload available.

Title: How do web developers deal with editing (pre-processed) vendor prefixed CSS in browser dev tools?

Body:
I have a dillema working with CSS. I use a pre-processor to add all necessary vendor prefixes to CSS when it's served, keeping my source code short and simple. However the issue is, by far the most effective way to to edit styles realistically (and see real-time updating of the page) is to use the web page's dev tools in whichever browser(s) you're currently testing, edit the CSS there, and copy/paste it to the source code after making significant changes.

So then my CSS source code is full of vendor prefixes.

Is there a simple solution to this? What solutions exist to solve this problem?


问:
How to populate Lazy object from database
I have these classes:

```<code>public class Order
{
    private Lazy<IEnumerable<Volume>> _volumes;
    long ID { get; private set; }
    string Description { get; private set; }
    IEnumerable<Volume> Volumes { get { return _volumes.Value; } }
    //etc..
}
public class Volume
{
    long ID { get; private set; }
    string Description { get; private set; }
    //etc..
}
</code>```

I need to instantiate and populate several Orders. To supply the objects of these classes I have these Repositories:

```<code>public interface IOrderRepository
{
    Order GetByID(long ID);
    IEnumerable<Order> GetAll();
    Order Create(long ID, string Description);
    void Update(Order O);
    void Delete(Order O);
}
public interface IVolumeRepository
{
    Volume GetByID(long ID);
    IEnumerable<Volume> GetAll(Order O);
    Volume Create(long ID, string Description, Order O);
    void Update(Volume V);
    void Delete(Volume V);
}
</code>```

I don't need to populate the Volumes of each Order upon instantiation, it would be best to implement lazy loading, in my opinion, as there can be a lot of Volumes.

So how should I let the Order know where to fetch the Volumes? I have this code that populates the Order it is instantiated:

```<code>//Interface
public interface IVolumeFetcher { IEnumerable<Volume> GetAll(Order O); }
//Order Constructor
public Order(long ID, string Description, IVolumeFetcher VF)
{
    _volumes = new Lazy<IEnumerable<Volume>>(() => VF.GetAll(this));
}
</code>```

This gives the Order a reference to the Repository, it doesn't seem a good idea to me.

I could keep the Order's Volumes a simple List and fill it when needed:

```<code>public List<Volume> Volumes { get; private set; }
</code>```

But this approach would be easily corrupted, any caller could add a Volume to the list and it wouldn't be persisted to the DB.
Btw, this is a three layered application, with a Order and Volume class for each layer, as well as a repository.

答:
Assuming transaction script over objects and no ORM.

You don't want your object to have repository code. Treat Lazy<T> as you would any constructor parameter, so the IOrderRepository will be responsible for providing it as a constructed object to the Order constructor.

```<code>public Order(long id, string description, Lazy<IEnumerable<Volume>> volumes)
{
    ...
    _volumes = volumes;
}
</code>```

If you are concerned about the repository reference sitting in the closure of Lazy<T> or needing to be disposed, since this usage is read-only, you could create and dispose an IVolumeRepository within the Lazy method:

```<code>// assuming IVolumeRepository is IDisposable or UOW
var volumes = new Lazy<IEnumerable<Volume>>(() =>
{
    //using (var repo = new ConcreteVolumeRepository())
    // or repo factory
    //using (var repo = volumeRepoFactoryFn())
    // or DI container
    using (var repo = DIContainer.Get<IVolumeRepository>())
    {
        return VF.GetAll(orderId))
    }
};

var order = new Order(orderId, description, volumes)
</code>```

If your repository is a singleton (not that it should be), then I would just do:

```<code>//IVolumeRepository volumeRepo ...
var orderId = ...
var description = ...
var volumes = new Lazy<IEnumerable<Volume>>(() => volumeRepo.GetAll(orderId));

var order = new Order(orderId, description, volumes);
</code>```

As a side note, your volume repository should load by order ID rather than order itself. I assume the IVolumeRepository.GetAll(Order O) method simply takes the ID property from the order, which is not useful to abstract away. If you want to make sure that it's an ID off an Order (versus any other kind of long), you can make OrderId a separate class or struct which wraps a long. That would accomplish the same purpose without causing a chicken-egg problem with loading Volumes. But I assume unit tests should provide sufficient verification without having to create a separate OrderId struct. (Why else would you use repository interfaces if not to unit test?)

Body:
Assuming transaction script over objects and no ORM.

You don't want your object to have repository code. Treat Lazy<T> as you would any constructor parameter, so the IOrderRepository will be responsible for providing it as a constructed object to the Order constructor.

public Order(long id, string description, Lazy<IEnumerable<Volume>> volumes)
{
    ...
    _volumes = volumes;
}

If you are concerned about the repository reference sitting in the closure of Lazy<T> or needing to be disposed, since this usage is read-only, you could create and dispose an IVolumeRepository within the Lazy method:

// assuming IVolumeRepository is IDisposable or UOW
var volumes = new Lazy<IEnumerable<Volume>>(() =>
{
    //using (var repo = new ConcreteVolumeRepository())
    // or repo factory
    //using (var repo = volumeRepoFactoryFn())
    // or DI container
    using (var repo = DIContainer.Get<IVolumeRepository>())
    {
        return VF.GetAll(orderId))
    }
};

var order = new Order(orderId, description, volumes)

If your repository is a singleton (not that it should be), then I would just do:

//IVolumeRepository volumeRepo ...
var orderId = ...
var description = ...
var volumes = new Lazy<IEnumerable<Volume>>(() => volumeRepo.GetAll(orderId));

var order = new Order(orderId, description, volumes);

As a side note, your volume repository should load by order ID rather than order itself. I assume the IVolumeRepository.GetAll(Order O) method simply takes the ID property from the order, which is not useful to abstract away. If you want to make sure that it's an ID off an Order (versus any other kind of long), you can make OrderId a separate class or struct which wraps a long. That would accomplish the same purpose without causing a chicken-egg problem with loading Volumes. But I assume unit tests should provide sufficient verification without having to create a separate OrderId struct. (Why else would you use repository interfaces if not to unit test?)


问:
Can there be value types in dynamic languages?
A value type is one whose instances are themselves saved in variables. A reference type is a type whose instances are saved somewhere and variables only hold the addresses of the instances.

Some languages, such as Java, have both types. For example String is a reference type and int is a value type.

```<code>public static void main(String[] args) {
    int i; // allocates 4 bytes on the stack, to store an actual integer value
    String s; // allocates 8 bytes on the stack (on 64 bit systems) to store an address
}
</code>```

This is possible in statically typed languages, because the type of i isn't going to change; so after allocating 4 bytes for it, we can put in it any integer value.

However, what if the type of i were dynamic? For example in Python, the following is possible:

```<code>def demonstrate():
    i = 20
    name = 'george'
    if input() == 'Make a string':
        i = 'hello'
    print('i is ' + i)
</code>```

All Python types are reference types. However suppose Python's int were a value type (and str still a reference type), and as a result we would try to actually put the number 20 inside i. In the stack after i, we would place an 8 byte reference to 'george'.

After that, we might want to change the value of i to 'hello'. This means reallocating room for it in the stack, instead of the room we previously allocated for the number 20.

My question is: is this possible (or practical)? Are there dynamic languages which support value types? If so, how?

答:
Yes, it’s possible, and in fact it’s common to “unbox” values of common types for performance reasons, usually with some form of “tagging” to indicate whether a value is boxed or unboxed.

The simplest possible representation is with one word for the type tag, and one word for the value or pointer, according to the tag.

```<code>enum Type { INTEGER, REFERENCE };

struct Value {
  Type type;
  union {
    uint64_t as_integer;
    Object *as_reference;
  } data;
};
</code>```

But we can do better. For example, heap allocations in many systems are aligned to 8-byte boundaries, which means that the bottom 3 bits of any pointer ((uintptr_t)p & 7) are guaranteed to be 0. As such, we can use these bits to store the tag, and thus get unboxed representations of common types with only one word. Here’s one simple such design, for a 32-bit system:

```<code>(x & 7) == 0 => (x & ~7) is a pointer
(x & 7) == 1 => (x >> 3) is an integer
</code>```

(This representation is used by OCaml, a statically typed language, to determine which values are references that need to be traced by the garbage collector.)

We could add up to 6 additional representations to this, for booleans and other common types we might wish to unbox, and a further 8 if we had a memory allocator that guaranteed 16-byte alignment.

In pointer magic for efficient dynamic value representations, Nikita Popov describes a system for embedding integers, booleans, and floating-point numbers in a single 64-bit word by making assumptions about the representation of floats (IEEE-754) and address spaces. A similar representation was used in Mozilla’s JägerMonkey JavaScript engine.

Body:
Yes, it’s possible, and in fact it’s common to “unbox” values of common types for performance reasons, usually with some form of “tagging” to indicate whether a value is boxed or unboxed.

The simplest possible representation is with one word for the type tag, and one word for the value or pointer, according to the tag.

enum Type { INTEGER, REFERENCE };

struct Value {
  Type type;
  union {
    uint64_t as_integer;
    Object *as_reference;
  } data;
};

But we can do better. For example, heap allocations in many systems are aligned to 8-byte boundaries, which means that the bottom 3 bits of any pointer ((uintptr_t)p & 7) are guaranteed to be 0. As such, we can use these bits to store the tag, and thus get unboxed representations of common types with only one word. Here’s one simple such design, for a 32-bit system:

(x & 7) == 0 => (x & ~7) is a pointer
(x & 7) == 1 => (x >> 3) is an integer

(This representation is used by OCaml, a statically typed language, to determine which values are references that need to be traced by the garbage collector.)

We could add up to 6 additional representations to this, for booleans and other common types we might wish to unbox, and a further 8 if we had a memory allocator that guaranteed 16-byte alignment.

In pointer magic for efficient dynamic value representations, Nikita Popov describes a system for embedding integers, booleans, and floating-point numbers in a single 64-bit word by making assumptions about the representation of floats (IEEE-754) and address spaces. A similar representation was used in Mozilla’s JägerMonkey JavaScript engine.


问:
How to make a datatype for something that represents either itself or two other things

Background

Here's the actual problem I'm working on: I want a way to represent cards in the card game Magic: The Gathering.  Most cards in the game are normal-looking cards, but some of them are divided into two parts, each with its own name.  Each half of these two-part cards is treated as a card itself.  So for clarity, I'll use Card only to refer to something that's either a regular card, or half of a two-part card (in other words, something with only one name).

So we have a base type, Card.  The purpose of these objects is really just to hold properties of the card.  They don't really do anything by themselves.

```<code>interface Card {
    String name();
    String text();
    // etc
}
</code>```

There are two subclasses of Card, which I'm calling PartialCard (half of a two-part card) and WholeCard (a regular card).  PartialCard has two additional methods: PartialCard otherPart() and boolean isFirstPart().

Representatives

If I have a deck, it should be composed of WholeCards, not Cards, as a Card could be a PartialCard, and that wouldn't make sense.  So I want an object that represents a "physical card," that is, something that can represent one WholeCard, or two PartialCards. I'm tentatively calling this type Representative, and Card would have the method getRepresentative().  A Representative would provide almost no direct information on the card(s) it represents, it would only point to it/them.  Now, my brilliant/crazy/dumb idea (you decide) is that WholeCard inherits from both Card and Representative.  After all, they are cards that represent themselves!  WholeCards could implement getRepresentative as return this;.

As for PartialCards, they don't represent themselves, but they have an external Representative that is not a Card, but provides methods for accessing the two PartialCards.

I think this type hierarchy makes sense, but it's complicated.  If we think of Cards as "conceptual cards" and Representatives as "physical cards," well, most cards are both!  I think you could make an argument that physical cards do in fact contain conceptual cards, and that they're not the same thing, but I would argue that they are.

Necessity of Type-casting

Because PartialCards and WholeCards are both Cards, and there's usually no good reason to separate them out, I'd normally just be working with Collection<Card>.  So sometimes I'd need to cast PartialCards in order to access their additional methods.  Right now, I'm using the system described here because I really don't like explicit casts.  And like Card, Representative would need be cast to either a WholeCard or Composite, to access the actual Cards they represent.

So just for summary:

Base type Representative

Base type Card

Type WholeCard extends Card, Representative (no access needed, it represents itself)

Type PartialCard extends Card (gives access to other part)

Type Composite extends Representative (gives access to both parts)

Is this insane?  I think it actually makes a lot of sense, but I'm honestly not sure.

答:
Maybe everything is a Card when it's in the deck or the graveyard, and when you play it, you construct a Creature, Land, Enchantment, etc. from one or more Card objects, all of which implement or extend Playable.  Then, a composite becomes a single Playable whose constructor takes two partial Cards, and a card with a kicker becomes a Playable whose constructor takes a mana argument. The type reflects what you can do with it (draw, block, dispel, tap) and what can effect it.  Or a Playable is just a Card that has to be carefully reverted (losing any bonuses and counters, getting split up) when taken out of play, if it’s really useful to use the same interface to invoke a card and predict what it does.

Perhaps Card and Playable have-a effect.


问:
Is remote agile sustainable?
This is somewhat related to another question i just asked, but I'm freelancing solo and remotely for a contractor who is to project management, what big ball of mud is to code, so to speak.

I've been thinking a lot about working on a proposition to deal with his projects in a truly agile way. As I see it, this would involve several client-friendly and web-based apps :

basecamp for communication

github as a repository

pivotal tracker for user-stories and as a display of work in progress

some tool to gather acceptance tests (will upvote suggestions !)

I've done a fair bit of reading on agile, and all good resources put much emphasis on the importance of communication in the team, to the point they are discouraging agile for non-colocated teams.
Being the only programmer this seemed less of an issue, but as I'll rarely meet the client (if at all), I'm worried the communication may not be effective enough to enable this kind of management.

Edit : Other people on the team would include :

- customers (business people)

- product manager (my client's client)

- project manager (my client)

- ui designer

答:
I have found that it can work well with everyone remote or everyone co located. If you have a mixture, the co located people will tend to communicate in ways which leave the remote people in the dark.

Instant messaging and/or irc can be great for remote teams. As it keep an always on means of communication with a log of what has been said for people to catch up on

Title: Is remote agile sustainable?


问:
Is hungarian notation a workaround for languages with insufficiently-expressive static typing?
In Eric Lippert's article What's Up With Hungarian Notation?, he states that the purpose of Hungarian Notation (the good kind) is to

extend the concept of "type" to encompass semantic information in addition to storage representation information.

A simple example would be prefixing a variable that represents an X-coordinate with "x" and a variable that represents a Y-coordinate with "y", regardless of whether those variables are integers or floats or whatever, so that when you accidentally write xFoo + yBar, the code clearly looks wrong.

But I've also been reading about Haskell's type system, and it seems that in Haskell, one can accomplish the same thing (i.e. "extend the concept of type to encompass semantic information") using actual types that the compiler will check for you. So in the example above, xFoo + yBar in Haskell would actually fail to compile if you designed your program correctly, since they would be declared as incompatible types. In other words, it seems like Haskell's type system effectively supports compile-time checking equivalent to Hungarian Notation

So, is Hungarian Notation just a band-aid for programming languages whose type systems cannot encode semantic information? Or does Hungarian Notation offer something beyond what a static type system such as Haskell's can offer?

(Of course, I'm using Haskell as an example. I'm sure there are other languages with similarly expressive (rich? strong?) type systems, though I haven't come across any.)

To be clear, I'm not talking about annotating variable names with the data type, but rather with information about the meaning of the variable in the context of the program. For example, a variable may be an integer or float or double or long or whatever, but maybe the variable's meaning is that it's a relative x-coordinate measured in inches. This is the kind of information I'm talking about encoding via Hungarian Notation (and via Haskell types).

答:
Hungarian notation was invented for BCPL, a language which didn't have types at all. Or rather, it had exactly one data type, the word. A word could be a pointer or it could be a character or boolean or a plain integer number depending on how you used it. Obviously this made it very easy to make horrible mistakes like dereferencing a character. So Hungarian notation was invented so the programmer could at least perform manual type checking by looking at the code.

C, a descendant of BCPL, has distinct types for integers, pointers, chars etc. This made the basic Hungarian notation superfluous to some extent (you didn't need to encode in the variable name if it was an int or a pointer), but semantics beyond this level still couldn't be expressed as types. This lead to the distinction between what has been called "Systems" and "Apps" Hungarian. You didn't need to express that a variable was an int, but you could use code-letters to indicate if the int was a say an x or y coordinate or an index.

More modern languages allow definitions of custom types, which means you can encode the semantic constraints in the types, rather then in the variable names. For example a typical OO language will have specific types for coordinate-pairs and areas, so you avoid adding an x coordinate to an y coordinate.

For example, in Joels famous article praising Apps Hungarian, he uses the example of the prefix us for an unsafe string, and s for a safe (html encoded) string, in order to prevent HTML-injection. The developer can prevent HTML-injection mistakes by simply carefully inspecting the code and ensyre that the variable prefixes match up. His example is in VBScript, a now obsolete language which didn't initially allow custom classes. In a modern language the problem can be fixed with a custom type, and indeed this is what Asp.net does with the HtmlString class. This way the compiler will automatically find the error, which is much safer that relying on human eyeballing. So clearly a language with custom types eliminates the need for "Apps Hungarian" in this case.

ContentLicense: CC BY-SA 4.0


问:
Benefit of non-volatile access to volatile objects being undefined?
This is a question about ISO C, which contains this sentence:

If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.

In ISO9899:1999 (C99) this appears in 6.7.3 Type Qualifiers.

Firstly, if we entirely removed this sentence from the text, would the behavior still be undefined? That is to say, is this re-stating an existing lack of a requirement, or is it explicitly taking away a requirement that could otherwise be inferred from elsewhere in the text?  (Imagine that a sentence were added which says "whenever two values of type int are added together whose arithmetic sum is forty-two, the behavior is undefined". Without such a sentence, the requirement for such an addition to produce a value can (and is) inferred).

Secondly, what useful behaviors does this allow an implementation to provide? That is to say, can an implementation do something beneficial which breaks programs that access something volatile with a non-volatile lvalue, and which therefore depends on the above sentence?  Are there any implementations which do this, whatever it is?

For example, it is interesting and noteworthy that C programs can access const-qualified objects with non-const lvalues, just not store to them. Making the store behavior undefined is tangibly beneficial: implementations can place constants in read-only storage, and in some cases can propagate constants through a program image at translation time as if they were manifest constants.  Yet, mere non-const access is required to work. Not requiring non-const accesses to const objects to work would presumably be a permissiveness  which brings no benefits.  Yet, in the case of volatile, it is that strict: no non-volatile-qualified access is required to work. What is the benefit?

Can an object which is defined as volatile by the C program itself be endowed with useful properties which break if there take place any accesses whatsoever to that object through a non-volatile lvalue?

(Under "useful", I would specifically like to exclude diagnosis. Terminating the program upon detecting such an access, without a message, or with a message like "volatile accessed as non-volatile" doesn't count as useful; it serves only to enforce the lack of requirement.)

(Also, I'm not interested in memory mapped registers and such; strictly objects defined by the program in static, dynamic or automatic storage. Use of hardware registers is inherently nonportable.)

All I can think of is that a non-volatile access to a volatile object could retrieve a stale value, rather than value that was last stored
(properly, through the volatile lvalue).  This is an economic benefit in the following way: if a write occurs through, say, a volatile int lvalue, the compiler does not have to suspect that this has any effect on any plain int lvalue. This leads to better code generation in functions which work with  mixtures volatile and non-volatile objects of the same type:

```<code>volatile int global;

void foo(int *p)
{
   int x = *p, y;
   global++;
   y = *p;
}
</code>```

Here, the compiler doesn't have to consider that *p might be an alias for global, because that usage is not required to work according to ISO C.  Hence it can freely assume that the value of *p does not change between the two references. Both x and y receive to the same value, derived from a single access to *p.

If the aliasing were permitted, then the compiler would have to generate code to re-load *p on the second access, in order that it pick up the most recent value stored in global.

(If we remove volatile from the above program fragment, then this is in fact the case; it has to be at least suspected, if not confirmed. that *p may be an alias for global and so *p has to be re-inspected. Or else code has to be generated which compares the run-time value of p to the address of global and takes two different paths.)

However, we don't introduce volatile into programs to obtain this kind of obscure optimization benefit; it is used to defeat optimization. The restrict keyword can be used instead to allow the implementation to reason about lvalues not being aliased. It seems that the above cannot be the rationale.

答: The volatile keyword means a lot of different things on a lot of different compilers, but one of their more important uses has been to represent special memory-mapped hardware.  So declaring the behavior in that respect undefined allows compilers to keep using it to represent that hardware. Same reason right-shift, divide and modulus of a negative signed integer is not specified exactly: that lets each CPU’s native instruction set work.  If you want exactly-defined behavior, there are atomics and div().


问:
Would it be possible to create functional, object oriented or declarative architectures?
My question originates from the fact that the most common architectures are inherently imperative (i.e. the machine language is imperative).

Would it be possible to create a computer architecture that is fundamentally functional, object oriented or declarative (or any other programming paradigm)? If so, would it be helpful?

答:
There are graph reduction CPUs like SKIM, GRIP, and perhaps most widely known, the Reduceron. (The Reduceron's instruction set is basically a subset of Haskell, i.e. a lazy functional language. It also has garbage collection in hardware.)

The FLEET and EDGE architectures focus heavily on communication. In the beginning of computing, computation was expensive, but communication (on the CPU) was practically free. Nowadays, it's the opposite: CPUs can compute insanely fast, it's moving the signals around the CPU that's the problem. But we can't influence communication: we can only tell the CPU to compute, communication on the CPU will happen as a side-effect of that, outside of our control. The FLEET architecture turns this upside down: you only tell the data where to go, computation happens as a side-effect of that.

The Azul Vega-3 CPU has a fairly traditional 3-address RISC instruction set, but its implementation is heavily optimized for object-oriented languages with dynamic polymorphism. So, it's not an object-oriented CPU, but it is a CPU optimized for object-orientation. E.g. OO code has much less locality of time and locality of space than ADT code. But most modern CPUs depend on temporal and spatial locality for a lot of their optimizations. These optimizations are mostly useless for OO languages, though. For example, memory prefetching to prevent cache misses. The Vega, instead of trying to prevent cache misses, reduces the cost of a cache miss by having an insane amount of memory bandwidth and a very sophisticated memory controller. (After all, the cost of cache misses is #misses * cost(miss), and bringing down either will reduce the total cost.) On a Vega system, you can have tens of thousands of cache misses in flight, and still make progress with your computation.


答:
All Python types are reference types.

That is wrong. (Well, kind of.)

However suppose Python's int were a value type

No need to suppose. It is a value type. (Well, kind of.)

To be precise, you can't tell whether it's a value type or a reference type. In Python, ints are immutable, and for immutable types it is impossible to tell whether they are value types or reference types, so ints might be either and you wouldn't know the difference. They are, however, implemented as value types in all Python implementations I know of, and the language in the Python doc/spec strongly suggests implementing them as value types.

Title: Can there be value types in dynamic languages?

Body:
A value type is one whose instances are themselves saved in variables. A reference type is a type whose instances are saved somewhere and variables only hold the addresses of the instances.

Some languages, such as Java, have both types. For example String is a reference type and int is a value type.

```<code>public static void main(String[] args) {
    int i; // allocates 4 bytes on the stack, to store an actual integer value
    String s; // allocates 8 bytes on the stack (on 64 bit systems) to store an address
}
</code>```

This is possible in statically typed languages, because the type of i isn't going to change; so after allocating 4 bytes for it, we can put in it any integer value.

However, what if the type of i were dynamic? For example in Python, the following is possible:

```<code>def demonstrate():
    i = 20
    name = 'george'
    if input() == 'Make a string':
        i = 'hello'
    print('i is ' + i)
</code>```

All Python types are reference types. However suppose Python's int were a value type (and str still a reference type), and as a result we would try to actually put the number 20 inside i. In the stack after i, we would place an 8 byte reference to 'george'.

After that, we might want to change the value of i to 'hello'. This means reallocating room for it in the stack, instead of the room we previously allocated for the number 20.

My question is: is this possible (or practical)? Are there dynamic languages which support value types? If so, how?


问:
Does Continuous Integration imply one monolithic VCS repo?
I am part of a small team which develops several internal apps for our company. We are in a process of becoming more Agile, this especially includes lots of automated testing. Now we are in a situation where, for the one or two apps which we have worked on most recently, we generally make small, reversible changes, run lots of tests, and deploy quite fast with not much human intervention.

I would consider us to be still a long way off from doing 'real' CI. For the one or two apps mentioned above we could probably get very close to it pretty soon. However, I am having a hard time imagining what our setup is going to look like, sometime in the future where we have started using CI for most of our legacy code.

Suppose we have several standalone apps, which all can be deployed independently to different servers. We also have some shared code which is used by many of them, and which we want to use consistently between them. This includes utility functions, code which enforces things like a consistent interface over some parts of all apps, and the ORM definitions for our database (shared across all apps).

I see two alternatives, neither of which looks very easy or elegant:

All code gets merged into one huge repo. Deployment means running all the tests for all the code, integration tests for everything and acceptance tests for all the apps, before rolling out everything in one go. This seems to make deployment a much Bigger Deal than it was before, contrary to the philosophy of CI, which suggests that it should be fast and easy. It also means we don't have any separation between different parts of our codebase, with things which never work together in the same repo forever, just because they both depend on some third thing.

We keep each app and each component of the shared code separate. Deployment means testing the latest version of one component extensively, before 'dropping it in' to a working system consisting of all other components. This seems like a cleaner design. However, it seems to imply that we have to manage dependencies and versioning for all these things. Every integration/acceptance test has to have some foreknowledge of what versions of the other components it is going to be used with and can tolerate. In other words, although every component becomes a lot more reliable, we have to worry loads more about how the pieces fit together, and integration bugs. When the pieces which everything else depends on change, there is potential for breakage eveywhere.

The way out of this dilemma is probably to do a limp version of CI, where the individual components get tested extensively and deployed quickly, but we stick to having big 'flag day' releases of the utilities and database schema. But it really seems like there are lots of benefits of proper CI/CD which we would be missing out on. It isn't an aesthetically pleasing solution, and we aren't looking to satisfy our bosses that we have ticked a box, but we want to improve our working practices.

How should we organize the code for proper CI, and what are the key lessons to learn about planning and designing the architecture, both for legacy and future newly written code?

答:
Imagine your code not as a monolithic system, but rather as a series of packages. Some packages depend on others. Some, such as jQuery, are external to your company; others are developed by your company and made public; others, developed by your company, are eventually made private.

For instance, if you develop a web application in Python, you may have a dependency to Flask—a popular Python web framework—and to a bunch of other packages, both external and internal.

What happens to your CI when developers of Flask release a new version? Right, nothing. It's up to you to go and edit your project file which says that from now on, you are not using the version x of Flask, but rather the version y. Once you do that, CI considers that your project changed, and launches all the tests which ensure that the application still works with the new version of Flask. If it doesn't, well, you'll probably fix your application, except in very rare cases where you actually reveal a bug in Flask itself.

The same logic can be applied to any code produced within your company. A shared library becomes a Python package, either shared through pypi—the repository of public packages for Python, or stored on a private pip server which can be used within your company only.

It then makes it particularly clear what broke the build. When you publish the new version of a package A, CI runs the corresponding tests and indicates whether the version contains regressions or not. Then, if a problem is encountered at the stage when you ask a package B to use the new version of the package A, it's the package B which broke the build by being incompatible with the new version of the package A: in the same way, your app may not be compatible with a newer version of Flask or jQuery.

Notice that you don't have to really manage dependencies yourself: the packaging system does it for you. The only problem which requires your intervention is the updating of the references, that is the action of telling that a given package will use a different version of another package: if you modified a package which is used a lot in your code base, it may take a while to track and modify all the projects which use it.

As for the version control, it really doesn't matter. You may have a team working with Git, and another one working with SVN. As soon as the two teams agree on using pypi and choosing specific pip server(s)¹ for internal packages, everything will be all right. Similarly, you shouldn't care whether developers of Flask or jQuery use Git, SVN, SourceSafe or TFS.

Note: I've used an example from Python world, but the same logic can be applied to other languages as well. There is npm for Node.js, NuGet for .NET Framework languages, etc. You can setup private package managers as well.

Further reading: Packages, dependencies and interaction between teams, my article based on this question.

¹ Nothing forces you to have a single package server in your company. Different teams can deploy their own servers; the only constraint is that other teams should know the location of the server in order to use the packages.


答:
CI systems support the organization of the work that they do into projects.  So, you can create as many different integration projects as you need, and each one of them will have a completely different set of preferences, including, of course, which repository root to check out from, where to deploy, etc.

That having been said, if you have modules that have tight dependencies on each other, then these modules should ideally be on the same repository.

By "tight dependencies" I do not mean something specific, but as a ballpark rule I would say that if you need to perform integration testing (as opposed to unit testing) between them, then that's probably worth calling it a tight dependency.

By "ideally" I mean that the benefits of keeping them in the same repository usually outweigh the disadvantages. But of course you know your code better, so it is up to you to decide.

Title: Does Continuous Integration imply one monolithic VCS repo?

Body:
I am part of a small team which develops several internal apps for our company. We are in a process of becoming more Agile, this especially includes lots of automated testing. Now we are in a situation where, for the one or two apps which we have worked on most recently, we generally make small, reversible changes, run lots of tests, and deploy quite fast with not much human intervention.

I would consider us to be still a long way off from doing 'real' CI. For the one or two apps mentioned above we could probably get very close to it pretty soon. However, I am having a hard time imagining what our setup is going to look like, sometime in the future where we have started using CI for most of our legacy code.

Suppose we have several standalone apps, which all can be deployed independently to different servers. We also have some shared code which is used by many of them, and which we want to use consistently between them. This includes utility functions, code which enforces things like a consistent interface over some parts of all apps, and the ORM definitions for our database (shared across all apps).

I see two alternatives, neither of which looks very easy or elegant:

All code gets merged into one huge repo. Deployment means running all the tests for all the code, integration tests for everything and acceptance tests for all the apps, before rolling out everything in one go. This seems to make deployment a much Bigger Deal than it was before, contrary to the philosophy of CI, which suggests that it should be fast and easy. It also means we don't have any separation between different parts of our codebase, with things which never work together in the same repo forever, just because they both depend on some third thing.

We keep each app and each component of the shared code separate. Deployment means testing the latest version of one component extensively, before 'dropping it in' to a working system consisting of all other components. This seems like a cleaner design. However, it seems to imply that we have to manage dependencies and versioning for all these things. Every integration/acceptance test has to have some foreknowledge of what versions of the other components it is going to be used with and can tolerate. In other words, although every component becomes a lot more reliable, we have to worry loads more about how the pieces fit together, and integration bugs. When the pieces which everything else depends on change, there is potential for breakage eveywhere.

The way out of this dilemma is probably to do a limp version of CI, where the individual components get tested extensively and deployed quickly, but we stick to having big 'flag day' releases of the utilities and database schema. But it really seems like there are lots of benefits of proper CI/CD which we would be missing out on. It isn't an aesthetically pleasing solution, and we aren't looking to satisfy our bosses that we have ticked a box, but we want to improve our working practices.

How should we organize the code for proper CI, and what are the key lessons to learn about planning and designing the architecture, both for legacy and future newly written code?


答:
The visitor pattern is a classic technique for recovering hidden type information. We can use it (a slight variation of it here) here to discern between the two types even when they are stored in higher-abstraction variables.

Let's start with that higher abstraction, a Card interface:

```<code>public interface Card {
    public void accept(CardVisitor visitor);
}
</code>```

There may be a little more behavior on the Card interface, but most of the property getters move to a new class, CardProperties:

```<code>public class CardProperties {
    // property methods, constructors, etc.

    String name();
    String text();
    // ...
}
</code>```

Now we can have a SimpleCard representing a whole card with a single set of properties:

```<code>public class SimpleCard implements Card {
    private CardProperties properties;

    // Constructors, ...

    @Override
    public void accept(CardVisitor visitor) {
        visitor.visit(properties);
    }
}
</code>```

We see how the CardProperties and the yet-to-be-written CardVisitor are starting to fit in. Let's do a CompoundCard to represent a card with two faces:

```<code>public class CompoundCard implements Card {
    private CardProperties firstFaceProperties;
    private CardProperties secondFaceProperties;

    // Constructors, ...

    public void accept(CardVisitor visitor) {
        visitor.visit(firstFaceProperties, secondFaceProperties);
    }
}
</code>```

The CardVisitor starts to emerge. Let's try to write that interface now:

```<code>public interface CardVisitor {
    public void visit(CardProperties properties);
    public void visit(CardProperties firstFaceProperties, CardProperties secondFaceProperties);
}
</code>```

(This is a first version of the interface for now. We can make improvements, which will be discussed later.)

We've now fleshed out all the parts. We now just need to put them together:

```<code>List<Card> cards = new LinkedList<>();
cards.add(new SimpleCard(new CardProperties(/* ... */)));
cards.add(new CompoundCard(new CardProperties(/* ... */), new CardProperties(/* ... */)));

 for(Card card : cards) {
     card.accept(new CardVisitor() {
         @Override
         public void visit(CardProperties properties) {
             // Do something for simple cards with a single face
         }

         public void visit(CardProperties firstFaceProperties, CardProperties secondFaceProperties) {
             // Do something else for compound cards with two faces
         }
     });
 }
</code>```

The runtime will handle the dispatch to the correct version of the #visit method through polymorphism rather than trying to break it.

Rather than use an anonymous class, you can even promote the CardVisitor to an inner class or even a full class if the behavior is reusable or if you want the ability to swap behavior at runtime.

We can use the classes as they are now, but there are some improvements we can make to the CardVisitor interface. For example, there may come a time when Cards can have three or four or five faces. Rather than adding new methods to implement, we could just have the second method take and array instead of two parameters. This makes sense if multi-faced cards are treated differently, but the number of faces above one are all treated similarly.

We could also convert CardVisitor to an abstract class instead of an interface, and have empty implementations for all the methods. This allows us to implement only the behaviors we are interested in (maybe we are only interested in single-faced Cards). We can also add new methods without forcing every existing class to implement those methods or fail to compile.

Title: How to make a datatype for something that represents either itself or two other things

Body:
Background

Here's the actual problem I'm working on: I want a way to represent cards in the card game Magic: The Gathering.  Most cards in the game are normal-looking cards, but some of them are divided into two parts, each with its own name.  Each half of these two-part cards is treated as a card itself.  So for clarity, I'll use Card only to refer to something that's either a regular card, or half of a two-part card (in other words, something with only one name).

So we have a base type, Card.  The purpose of these objects is really just to hold properties of the card.  They don't really do anything by themselves.

```<code>interface Card {
    String name();
    String text();
    // etc
}
</code>```

There are two subclasses of Card, which I'm calling PartialCard (half of a two-part card) and WholeCard (a regular card).  PartialCard has two additional methods: PartialCard otherPart() and boolean isFirstPart().

Representatives

If I have a deck, it should be composed of WholeCards, not Cards, as a Card could be a PartialCard, and that wouldn't make sense.  So I want an object that represents a "physical card," that is, something that can represent one WholeCard, or two PartialCards. I'm tentatively calling this type Representative, and Card would have the method getRepresentative().  A Representative would provide almost no direct information on the card(s) it represents, it would only point to it/them.  Now, my brilliant/crazy/dumb idea (you decide) is that WholeCard inherits from both Card and Representative.  After all, they are cards that represent themselves!  WholeCards could implement getRepresentative as return this;.

As for PartialCards, they don't represent themselves, but they have an external Representative that is not a Card, but provides methods for accessing the two PartialCards.

I think this type hierarchy makes sense, but it's complicated.  If we think of Cards as "conceptual cards" and Representatives as "physical cards," well, most cards are both!  I think you could make an argument that physical cards do in fact contain conceptual cards, and that they're not the same thing, but I would argue that they are.

Necessity of Type-casting

Because PartialCards and WholeCards are both Cards, and there's usually no good reason to separate them out, I'd normally just be working with Collection<Card>.  So sometimes I'd need to cast PartialCards in order to access their additional methods.  Right now, I'm using the system described here because I really don't like explicit casts.  And like Card, Representative would need be cast to either a WholeCard or Composite, to access the actual Cards they represent.

So just for summary:

Base type Representative

Base type Card

Type WholeCard extends Card, Representative (no access needed, it represents itself)

Type PartialCard extends Card (gives access to other part)

Type Composite extends Representative (gives access to both parts)

Is this insane?  I think it actually makes a lot of sense, but I'm honestly not sure.

Body:
The visitor pattern is a classic technique for recovering hidden type information. We can use it (a slight variation of it here) here to discern between the two types even when they are stored in higher-abstraction variables.

Let's start with that higher abstraction, a Card interface:

public interface Card {
    public void accept(CardVisitor visitor);
}

There may be a little more behavior on the Card interface, but most of the property getters move to a new class, CardProperties:

public class CardProperties {
    // property methods, constructors, etc.

    String name();
    String text();
    // ...
}

Now we can have a SimpleCard representing a whole card with a single set of properties:

public class SimpleCard implements Card {
    private CardProperties properties;

    // Constructors, ...

    @Override
    public void accept(CardVisitor visitor) {
        visitor.visit(properties);
    }
}

We see how the CardProperties and the yet-to-be-written CardVisitor are starting to fit in. Let's do a CompoundCard to represent a card with two faces:

public class CompoundCard implements Card {
    private CardProperties firstFaceProperties;
    private CardProperties secondFaceProperties;

    // Constructors, ...

    public void accept(CardVisitor visitor) {
        visitor.visit(firstFaceProperties, secondFaceProperties);
    }
}

The CardVisitor starts to emerge. Let's try to write that interface now:

public interface CardVisitor {
    public void visit(CardProperties properties);
    public void visit(CardProperties firstFaceProperties, CardProperties secondFaceProperties);
}

(This is a first version of the interface for now. We can make improvements, which will be discussed later.)

We've now fleshed out all the parts. We now just need to put them together:

List<Card> cards = new LinkedList<>();
cards.add(new SimpleCard(new CardProperties(/* ... */)));
cards.add(new CompoundCard(new CardProperties(/* ... */), new CardProperties(/* ... */)));

 for(Card card : cards) {
     card.accept(new CardVisitor() {
         @Override
         public void visit(CardProperties properties) {
             // Do something for simple cards with a single face
         }

         public void visit(CardProperties firstFaceProperties, CardProperties secondFaceProperties) {
             // Do something else for compound cards with two faces
         }
     });
 }

The runtime will handle the dispatch to the correct version of the #visit method through polymorphism rather than trying to break it.

Rather than use an anonymous class, you can even promote the CardVisitor to an inner class or even a full class if the behavior is reusable or if you want the ability to swap behavior at runtime.

We can use the classes as they are now, but there are some improvements we can make to the CardVisitor interface. For example, there may come a time when Cards can have three or four or five faces. Rather than adding new methods to implement, we could just have the second method take and array instead of two parameters. This makes sense if multi-faced cards are treated differently, but the number of faces above one are all treated similarly.

We could also convert CardVisitor to an abstract class instead of an interface, and have empty implementations for all the methods. This allows us to implement only the behaviors we are interested in (maybe we are only interested in single-faced Cards). We can also add new methods without forcing every existing class to implement those methods or fail to compile.


答:
To be blunt, I think the proposed solution is too restrictive and too contorted and disjointed from the physical reality is models, with little advantage.

I'd suggest one of two alternatives:

Option 1.
Treat it as single card, identified as Half A // Half B, like the MTG site lists Wear // Tear. But, permit your Card entity to contain N of each attribute: playable-name, mana cost, type, rarity, text, effects, etc..

```<code>interface Card {
  List<String> Names();
  List<ManaCost> Costs();
  List<CardTypes> Types();
  /* etc. */
}
</code>```

Option 2. Not all that dissimilarly from Option 1, model it after the physical reality. You have a Card entity that represents a physical card. And, it's purpose is then to hold N Playable things. Those Playable's can each have a distinct name, mana cost, list of effects, list of abilities, etc.. And your "physical" Card can have its own identifier (or name) that is a compound of each Playable's name, much like the MTG database appears to do.

```<code>interface Card {
  String Name();
  List<Playable> Playables();
}

interface Playable {
  String Name();
  ManaCost Cost();
  CardType Type();
  /* etc. */
}
</code>```

I think either of these options are pretty close to the physical reality. And, I think that'll be beneficial to anyone who looks at your code. (Like your own self in 6 months.)

Body:
To be blunt, I think the proposed solution is too restrictive and too contorted and disjointed from the physical reality is models, with little advantage.

I'd suggest one of two alternatives:

Option 1.
Treat it as single card, identified as Half A // Half B, like the MTG site lists Wear // Tear. But, permit your Card entity to contain N of each attribute: playable-name, mana cost, type, rarity, text, effects, etc..

interface Card {
  List<String> Names();
  List<ManaCost> Costs();
  List<CardTypes> Types();
  /* etc. */
}

Option 2. Not all that dissimilarly from Option 1, model it after the physical reality. You have a Card entity that represents a physical card. And, it's purpose is then to hold N Playable things. Those Playable's can each have a distinct name, mana cost, list of effects, list of abilities, etc.. And your "physical" Card can have its own identifier (or name) that is a compound of each Playable's name, much like the MTG database appears to do.

interface Card {
  String Name();
  List<Playable> Playables();
}

interface Playable {
  String Name();
  ManaCost Cost();
  CardType Type();
  /* etc. */
}

I think either of these options are pretty close to the physical reality. And, I think that'll be beneficial to anyone who looks at your code. (Like your own self in 6 months.)